0

当表单处于可编辑模式时,我需要在 primefaces 数据表中包含 inputTexts。

除了使用 immediate="true" 进行表单清理(没有表单验证)外,一切都正常工作。然后 primefaces 数据表的行为不可预测。用新数据填充数据表后 - 它仍然存储旧值。

简短示例 - 显示 h:dataTable 和 p:dataTable 之间的差异 -但当示例中只有三个表之一时,它的工作方式相同:test.xhtml

<h:body>
    <h:form id="form">

        <p:dataTable var="v" value="#{test.list}" id="testTable">
            <p:column headerText="Test value">
                <p:inputText value="#{v}"/>
            </p:column>
        </p:dataTable>

        <h:dataTable var="v" value="#{test.list}" id="testTable1">
            <h:column>
            <f:facet name="header">
                <h:outputText value="Test value" />
            </f:facet>
                <p:inputText value="#{v}" />
            </h:column>
        </h:dataTable>

        <p:dataTable var="v" value="#{test.list}" id="testTable2">
            <p:column headerText="Test value">
                <h:outputText value="#{v}" />
            </p:column>
        </p:dataTable>

        <p:commandButton value="Clear" actionListener="#{test.clear()}" immediate="true" update=":form:testTable :form:testTable1 :form:testTable2"/>
        <p:commandButton value="Update" actionListener="#{test.update()}" update=":form:testTable :form:testTable1 :form:testTable2"/>
    </h:form>
</h:body>

和java:

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@ViewScoped
public class Test implements Serializable {

    private static final long serialVersionUID = 1L;

    private List<String>            list;



    @PostConstruct
    private void init(){
        update();
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void clear() {
        list = new ArrayList<String>();
    }

    public void update() {
        list = new ArrayList<String>();
        list.add("Item 1");
        list.add("Item 2");     
    }
}

在上面的示例中,我有 3 个配置: 1. p:dataTable 和 p:inputText 2. h:dataTable 和 p:inputText 3. p:dataTable 和 h:outputText

和 2 个按钮:第一个清除数据,第二个应用数据

工作流程:

  1. 尝试更改 p:dataTable 和 h:dataTable 中 inputTexts 中的数据

  2. 清除列表数据(字符串数组列表) - 单击“清除”按钮(假设您在表单上单击取消,因为您不想将数据存储到数据库)

  3. 加载新数据 - 单击“更新”按钮(假设您正在使用新数据打开新表单)

问题: 为什么 p:dataTable 和 p:inputText 仍然存储手动更改的数据,而不是加载的数据?在这种情况下,有没有办法强制 p:dataTable 表现得像 h:dataTable ?

4

2 回答 2

5

解决办法是:primefaces resetInput

在我的示例中,它将是:

 <p:commandButton value="Clear" actionListener="#{test.clear()}" immediate="true"
          update=":form:testTable :form:testTable1 :form:testTable2"> 
    <p:resetInput target=":form:testTable" />
 </p:commandButton>


编辑: 在某些情况下 - 如果上述方法不起作用 - 尝试 primefaces 扩展中的一个:

<pe:resetInput for=":form:testTable" />
于 2012-12-18T16:04:44.700 回答
2

您遇到的问题是在提交表单时,正在为绑定到表单中此列表的#{test.list}每个数据表(<p>或)提交值。<h>换句话说:

  • JSF 会将数据表的值绑定testTable到您的#{test.list}.

  • JSF 会将数据表的值绑定testTable1到您的#{test.list}. 这些值将替换从数据表绑定的值testTable,并且那里的数据将丢失。#{test.list}将包含 中的数据testTable1

  • JSF 会将数据表的值绑定testTable2到您的#{test.list}. 由于此处的值是旧值,因此这些值将是提交的值#{test.list}

解决此问题的最佳方法是在托管 bean 中使用单个<p:dataTable>(或<h>,取决于您的需要)和一个属性来控制您的表是处于查看模式还是编辑模式。

JSF 代码

<h:form id="form">
    <p:dataTable var="v" value="#{test.list}" id="testTable">
        <p:column headerText="Test value">
            <h:outputText value="#{v}" rendered="#{not test.editMode}" />
            <p:inputText value="#{v}" rendered="#{test.editMode}" />
        </p:column>
    </p:dataTable>

    <p:commandButton value="Clear" actionListener="#{test.clear()}" immediate="true"
        update="testTable" />
    <p:commandButton value="Update" actionListener="#{test.update()}"
        update="testTable" />
    <!-- adding a new button just for testing purposes -->
    <p:commandButton value="Submit list" action="#{test.submit}" />
</h:form>

托管 Bean 代码

//no need of CDI
@ManagedBean
@ViewScoped
public class Test implements Serializable {

    private List<String> list;
    private boolean editMode = false;

    public Test() {

    }

    @PostConstruct
    private void init(){
        update();
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void clear() {
        list = new ArrayList<String>();
    }

    public void update() {
        list = new ArrayList<String>();
        list.add("Item 1");
        list.add("Item 2");     
    }

    //method for testing purposes
    public void submit() {
        //in real life web apps, you should log the messages, don't use System.out
        System.out.println("Showing actual values of list attribute.");
        for(String s : list) {
            System.out.println(s);
        }
    }
}
于 2012-12-15T17:35:56.877 回答