JSF 2.0、CDI、EJB、JPAなどの標準のJavaEEコンポーネントを使用してサイトを設計しています。初期段階なので、ナビゲーションは非常に簡単です。問題は、ナビゲートするときに一部のデータを保持するのが難しいことです。
これがseminarController
バッキングBeanです。
SeminarController.java
@Named
@RequestScoped
public class SeminarController {
@Inject
private SeminarDao seminarDao;
private int seminarID;
private Seminar seminar;
...
// Getters and setters
...
public Collection<Seminar> getSeminars() {...}
public Collection<Seminar> getUpcomingSeminars() {...}
public void initSeminar() {
seminar = seminarDao.findSeminar(seminarID);
}
public String save() {
seminarDao.save(seminar);
return "details";
}
}
最初のページは現在、間もなく開催される可能性のあるいくつかのセミナーを一覧表示しています。
index.xhtml
<ul>
<ui:repeat value="#{seminarController.upcomingSeminars}" var="seminar">
<li>
<h:link value="#{seminar.title}" outcome="details">
<f:param name="id" value="#{seminar.seminarID}"/>
</h:link>
on
<h:outputText value="#{seminar.eventDate}"/>
</li>
</ui:repeat>
</ul>
ご覧のとおり、リンクをクリックすると詳細ページに移動するリンクのリストがあります。f:param
セミナーのIDをHTTPリクエストパラメータに追加するために使用しています。
詳細ページには、今後のセミナーに関する詳細が(もちろん)表示されます。リンクをクリックしてセミナーを編集することもできます。
details.xhtml
<f:metadata>
<f:viewParam name="id" value="#{seminarController.seminarID}"/>
<f:event type="preRenderView" listener="#{seminarController.initSeminar}"/>
</f:metadata>
<ui:define name="body">
<h2>#{seminarController.seminar.title}</h2>
<p>
<strong>When:</strong>
#{seminarController.seminar.eventDate}
</p>
<p>
<strong>Where:</strong>
#{seminarController.seminar.address},
#{seminarController.seminar.country}
</p>
...
<p>
<h:link value="Edit" outcome="edit">
<f:param name="id" value="#{seminarController.seminarID}"/>
</h:link> |
<h:link value="Back to List" outcome="index"/>
</p>
これまでのところ、すべてが正常に機能しています。
リンクをたどってセミナーを編集し、編集ページに移動します。f:param
現在のセミナーのIDにはまだ使用しています。
edit.xhtml
<f:metadata>
<f:viewParam name="id" value="#{seminarController.seminarID}"/>
<f:event type="preRenderView" listener="#{seminarController.initSeminar}"/>
</f:metadata>
<ui:define name="body">
<h:form>
<h:messages title="Please correct the errors and try again."/>
<fieldset>
<h:panelGroup class="editor-label" layout="block">
<h:outputLabel value="Seminar Title:" for="title"/>
</h:panelGroup>
<h:panelGroup class="editor-field" layout="block">
<h:inputText id="title" value="#{seminarController.seminar.title}"/>
<h:message for="title" title="*"/>
</h:panelGroup>
...
<p>
<h:commandButton value="Save" action="#{seminarController.save}">
<f:param id="id" value="#{seminarController.seminar.seminarID}"/>
</h:commandButton>
</p>
</fieldset>
</h:form>
これは私が問題を抱え始めているところです。保存ボタンを押したら詳細ページに戻りたい。詳細ページには、新しく更新された詳細とともに現在のセミナーが表示されます。問題は、[保存]ボタンが押されたときに、のseminar
オブジェクトがであるということseminarController
ですnull
。
編集ビューがレンダリングされると、セミナーオブジェクトが初期化され、フォームに現在の値を表示するために使用されます。ただし、[保存]ボタンを押すと、セミナーオブジェクトはに存在しなくなりますseminarController
。また、initSeminar
メソッドも呼び出されません。
では、問題は、デザイン-編集-デザインページのナビゲーションをどのように設計する必要があるかということです。
[保存]を押すと新しいビューに移動しているため、ViewScopeは機能しません。とにかくCDIを使用する場合、ViewScopeは存在しません。
どんな助けでもありがたいです!
編集
ゼミのクラスには、フォームに表示されないフィールドがいくつかあります。
Seminar.java
@Entity
public class Seminar {
@Id
private int seminarID;
@Column
private String title;
@Column
private Date eventDate; // Date when the seminar occurs
@Column
private Date createdDate; // Not visible in forms
...
// Some more fields and Getters/Setters
}
Edit2:
SeminarController
私はこれを:でやることになりました
SeminarController.java
@PostConstruct
public void init() {
if (FacesContext.getCurrentInstance().isPostback()) {
seminar = new Seminar();
} else {
seminar = seminarDao.findSeminar(seminarID);
}
}
public void setSeminarID(int seminarID) {
if (this.seminarID != seminarID) {
seminar = seminarDao.findSeminar(seminarID);
this.seminarID = seminarID;
}
}
public String save() {
seminarDao.save(seminar);
return "details?faces-redirect=true&includeViewParams=true";
}
そして、にを追加し<h:inputHidden value="#{seminarController.seminarID}"/>
ましたedit.xhtml
。
それに応じて、古いの代わりにメソッドを呼び出すように<f:event/>
変更されましdetails.xhtml
た。edit.xhtml
init()
initSeminar()
seminar
これはうまくいくようですが、オブジェクトがポストバックで使用new
して作成され、設定時に上書きされるのはあまり好きではありませんseminarID
。