我面临着JSF和Datatables的一些麻烦。在我的bean中,我有一个依赖于Datatable的视图中显示的对象列表。对象是 非常简单,每个都由一个整数(id)和一个String( 注释)。
最终目标是向用户打印完整的对象列表,同时编辑一行或多行(通过h:inputtext字段),然后通过按钮提交更改。这就是问题所在。我已经成功使用了#34;"数据表通过依赖每行上的编辑/保存按钮每次编辑一行,但在这种情况下不适用,因为最终用户将面对总计超过500行。
这是我使用的代码(简化和提取)
豆:
@ManagedBean
@RequestedScope
public class VlanBean {
private DataModel<VlanWrapper> model;
private List<VlanWrapper> vlans = new ArrayList<VlanWrapper>();
public VlanBean() {
vlans.add(new VlanWrapper(1, ""));
vlans.add(new VlanWrapper(2, "Prova2-2"));
vlans.add(new VlanWrapper(3, ""));
vlans.add(new VlanWrapper(4, ""));
vlans.add(new VlanWrapper(5, ""));
vlans.add(new VlanWrapper(6, "Prova3"));
vlans.add(new VlanWrapper(7, ""));
vlans.add(new VlanWrapper(8, ""));
}
public void commitChanges()
{
System.out.println("Before Model ");
for (VlanWrapper vw : model)
{
System.out.println("ModelOF " + vw.getId() + " - " + vw.getProject() + " - changed: " + vw.changed + ";");
}
}
public DataModel<VlanWrapper> getModel() {
if (model == null)
model = new ListDataModel<VlanWrapper>(vlans);
return model;
}
public void setModel(DataModel<VlanWrapper> model) {
this.model = model;
}
public class VlanWrapper
{
private boolean changed;
private int id;
private String project;
public VlanWrapper(int id, String prj)
{
this.id = id;
this.project = prj;
changed = false;
}
public String getProject() {
return project;
}
public void setProject(String project) {
System.out.println("Setting PRJ..");
changed = true;
this.project = project;
}
public int getId() {
return id;
}
public boolean isChanged() {
return changed;
}
}
}
查看:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
<f:view>
<h:panelGroup>
<h:form>
<h:commandButton value="Commit changes to DB" action="#{VlanBean.commitChanges}">
</h:commandButton>
</h:form>
<h:dataTable value="#{VlanBean.model}" var="vlans">
<h:column><f:facet name="header">ID</f:facet>#{vlans.id}</h:column>
<h:column><f:facet name="header">Project</f:facet>
<h:inputText value="#{vlans.project}" immediate="true"/>
</h:column>
</h:dataTable>
</h:panelGroup>
</f:view>
</h:body>
</html>
问题是我在视图上做的所有更改都没有反映在bean中,我没有找到任何有用的提示/帖子(一些建议ajax强制更新,其他javascript,但我没有&# 39;使它们中的任何一个都工作,没有人真正接近我想要的用途。
我也试图去找ui:重复,但我有同样的行为。有什么想法/建议吗?我没有义务使用Datatable,所以我对其他解决方案/方法开放了!
先谢谢, 阿尔贝托
答案 0 :(得分:0)
从您的代码中,您应该收到一条警告,说明您的<h:inputText
应该有<f:form
为父母;周围没有形式,你所拥有的形式就在<h:commandButton
使用任何类型的Iteration
UIComponent都可以获得所需的行为,尽管通常使用<h:datatable
。虽然您必须先选择要编辑的行,但我确保您可以自行找到解决方案,但您可以采用以下方法:
我向您的实体VlanWrapper
添加了另一个属性:
private boolean changed;
private boolean edit;
private int id;
private String project;
// setters&amp;吸气鬼......
你的面孔可能是这样的:
<h:form>
<h:dataTable value="#{meod.vlans}" var="v" >
<h:column>
<f:facet name="header">Id</f:facet>
<h:outputLabel value="#{v.id}" />
</h:column>
<h:column>
<f:facet name="header">Project</f:facet>
<h:outputLabel rendered="#{not v.edit}" value="#{v.project}" />
<h:inputText rendered="#{v.edit}" value="#{v.project}" >
<f:ajax event="blur" execute="@this" listener="#{meod.addToEditedList(e)}" render="@all">
<f:param name="vlanedit" value="#{v.id}" />
<f:param name="vlanproject" value="#{v.project}" />
</f:ajax>
</h:inputText>
</h:column>
<h:column>
<f:facet name="header">Edit</f:facet>
<h:commandButton value="Edit" action="#{meod.edit(v)}">
<f:ajax render="@form" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Finalize Edit" action="#{meod.editSubmit()}" />
</h:form>
我说您必须选择要编辑的行的原因是因为当您按下edit
按钮时,整个表单将会更新,所以只需要更新您想要更新的内容,这应该做它
支持大豆:
@ManagedBean
@ViewScoped
public class Meod {
private List<VlanWrapper> vlans;
public Meod() {
vlans = new ArrayList<>();
for (int i = 0; i < 11; i++) {
vlans.add(new VlanWrapper(i, "Project " + i));
}
}
public void addToEditedList(AjaxBehaviorEvent e) {
Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
int id = Integer.valueOf(params.get("vlanedit"));
String newProject = params.get("vlanproject");
updateVlanInView(id, newProject);
}
private void updateVlanInView(int id, String proj) {
vlans.stream().filter(v -> v.getId() == id).forEach(v -> v.setProject(proj));
}
public void edit(VlanWrapper vlan2Edit) {
vlan2Edit.setEdit(true);
}
public void editSubmit() {
vlans.forEach((v) -> v.setEdit(false));
}
public List<VlanWrapper> getVlans() {
return vlans;
}
public void setVlans(List<VlanWrapper> vlans) {
this.vlans = vlans;
}
}
有多种方法可以实现这一目标......可能是更好的方法,但总结一下:
<h:commandXXX
和EditableValueHolder
位于表单中。edit
用于确定是否呈现输入而不是输出文本组件希望这有帮助。
答案 1 :(得分:0)
在数据表之后移动</h:form>
标记。现在,这将包括您的更改,现在可以正确调用setProject方法。
<h:panelGroup>
<h:form>
<h:commandButton value="Commit changes to DB" action="#{VlanBean.commitChanges}">
</h:commandButton>
<h:dataTable value="#{VlanBean.model}" var="vlans">
<h:column><f:facet name="header">ID</f:facet>#{vlans.id}</h:column>
<h:column><f:facet name="header">Project</f:facet>
<h:inputText value="#{vlans.project}" immediate="true"/>
</h:column>
</h:dataTable>
</h:form>
</h:panelGroup>