我正在使用标准Java EE组件(如JSF 2.0,CDI,EJB和JPA)设计站点。它处于早期阶段,因此导航非常简单。问题是我在导航时难以保留一些数据。
这是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不起作用,因为我在按Save时导航到新视图。无论如何使用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
时覆盖它。
答案 0 :(得分:2)
您需要在更新模型值阶段发生之前自己准备seminar
。预渲染视图事件太晚了。
其中一种方法是创建@PostConstruct
,其中检查当前请求是否为回发,如果是,则预先调整Seminar
,以便JSF有机会在更新模型期间调用其setter价值观阶段。
@PostConstruct
public void init() {
if (FacesContext.getCurrentInstance().isPostback()) {
seminar = new Seminar();
}
}
我不确定initSeminar()
做了什么,但我认为您还需要相应地更改它if (!FacesContext.getCurrentInstance().isPostback())
。