我试图实现表与用户的帐户,这可以由管理员修改。我使用primefaces (2.2) DataTable组件与cellitor。
我有onRowEditListener,它使用manageUsers.onEditRow()方法通过UserDAO对象在数据库中持久化更改。
加载页面并更新表单元格后,数据库中的数据正确更改。不幸的是,当我试图再次更新前一行- (UserDAO)event.getObject();
返回旧对象(第一次更改后的对象)和数据不更新。
当我重新加载页面(F5)和编辑行-然后数据被正确更改。
如何更新表或如何在不重新加载页面的情况下获得最新版本的用户?
使用Primefaces 2.2, JSF 2.1, Glassfish 3.1
页面:
<p:column headerText="login" filterBy="#{u.user.login}" filterMatchMode="contains" style="width:150px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.user.login}" />
</f:facet>
<f:facet name="input">
<h:form>
<p:inputText value="#{u.user.login}" />
</h:form>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="email" filterBy="#{u.user.email}" filterMatchMode="contains" style="width:150px">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{u.user.email}" />
</f:facet>
<f:facet name="input">
<h:form>
<p:inputText value="#{u.user.email}" />
</h:form>
</f:facet>
</p:cellEditor>
</p:column>
//... other fields
<p:column headerText="Options">
<p:rowEditor />
</p:column>
</p:dataTable>
</h:form>
ManageBean with ApplicationScope (CDI)
@Named
@ApplicationScoped
public class ManageUsers implements Serializable {
@Inject
/** Inject database */
private DB db;
/** List with all leaked data which is loaded from database */
private List<UserDAO> users;
private User selectedUser;
private SelectItem[] manufacturerOptions;
public ManageUsers() {
manufacturerOptions = createFilterOptions();
}
public SelectItem[] getManufacturerOptions() {
return manufacturerOptions;
}
public User getSelectedUser() {
return selectedUser;
}
public void setSelectedUser(User selectedUser) {
this.selectedUser = selectedUser;
}
/** List of users loaded from database */
public void getDataFromDatabase() {
try {
users = db.getUserList();
if (users == null) {
throw new Exception("Pusta lista użytkowników");
}
} catch (Exception ex) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR,
"Nie można wyświetlić tabeli wyników",
"Nie udało się pobrać danych, prosimy spróbować ponownie później.");
FacesContext.getCurrentInstance().addMessage(null, message);
}
}
/**
* Get list of leaked Data.
* If list is null then getDataFromDatabase method is used.
* @see DataExplorer.getDataFromDatabase()
*/
public List<UserDAO> getUsers() {
if (users == null) {
getDataFromDatabase();
}
return users;
}
private SelectItem[] createFilterOptions() {
SelectItem[] options = new SelectItem[3];
options[0] = new SelectItem("", "-select-");
options[1] = new SelectItem("true", "Admins");
options[2] = new SelectItem("false", "Users");
return options;
}
public void onEditRow(RowEditEvent event){
UserDAO userDAO = (UserDAO)event.getObject();
try {
userDAO.update();
} catch (UserDAOException ex) {
Log.logger.error("User not edited,"+ex);
}
//getDataFromDatabase();
}
}
您总是返回一个新列表,这是JSF中众所周知的坏做法,在getter中获取数据。在JSF生命周期中,getter可能被调用多次。在变量中缓存用户列表,最好使用视图作用域。
内联编辑/更新实际上是工作的,但你失去了更新的模型,每次返回一个新的列表。
我不知道我是否真的理解你的问题,但你可以很容易地更新你的表,甚至更好地更新你的表单,但实现一个commandButton与更新属性:
假设您有一个表单,它的id是myTableForm
,然后在该表单中您有您的dataTable组件和commandButton组件。这个按钮看起来像这样:
<p:commandButton ajax='true' value='PersistData' update='myTableForm' action='if really needed' />
你只能在需要的时候引用一个动作方法。否则,这个按钮只会通过实现一个ajax请求来更新整个表单。Ajax默认为true,但我在那里显式地添加了该属性。
当然你可以有另一个逻辑设计…你不需要实现一个按钮来做到这一点,你可以有一些ajax监听器,一些javascript函数,将触发在页面加载,编辑单元格等…我选择了一个命令按钮,因为这是理解逻辑的最简单的方法…
请让我知道,如果这真的是你想要的。
问题解决。p:inputText =_=