JSF Datatable:通过单个命令按钮提交多行

时间:2016-11-24 17:50:20

标签: jsf jsf-2 datatable

我面临着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,所以我对其他解决方案/方法开放了!

先谢谢, 阿尔贝托

2 个答案:

答案 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:commandXXXEditableValueHolder位于表单中。
  • &#34; new&#34; property edit用于确定是否呈现输入而不是输出文本组件
  • 使用DBService在更改后更新值。

希望这有帮助。

答案 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>