InputText внутри таблицы данных Primefaces не обновляется

Мне нужно, чтобы inputTexts внутри первичных данных были доступны, когда форма находится в редактируемом режиме.

Все работает правильно, кроме очистки формы с немедленной = "true" (без проверки формы). Тогда данные простых граней ведут себя непредсказуемо. После заполнения datatable новыми данными - он все равно хранит старые значения.

Короткий пример — чтобы показать различия между 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>

И джава:

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. Попробуйте изменить данные в inputTexts в p:dataTable и h:dataTable

  2. Очистить данные списка (arrayList of string) - нажмите кнопку «очистить» (представьте, что вы нажимаете «Отмена» в форме, потому что не хотите сохранять данные в базе данных)

  3. Загрузить новые данные - нажмите кнопку "обновить" (представьте, что вы открываете новую форму с новыми данными)

Вопрос: Почему p:dataTable с p:inputText по-прежнему хранит измененные вручную данные, а не загруженные? Есть ли способ заставить p: dataTable вести себя как h: dataTable в этом случае?


person robson    schedule 15.12.2012    source источник


Ответы (2)


Решение таково: 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" />
person robson    schedule 18.12.2012

Проблема, с которой вы столкнулись, заключается в том, что при отправке формы значения #{test.list} отправляются для каждой таблицы данных (<p> или <h>), привязанной к этому списку в форме. Другими словами:

  • JSF привяжет значения таблицы данных testTable к вашему файлу #{test.list}.

  • JSF привяжет значения таблицы данных testTable1 к вашему файлу #{test.list}. Эти значения заменят значения, привязанные к testTable datatable, и данные там будут потеряны. #{test.list} будет содержать данные из testTable1.

  • JSF привяжет значения таблицы данных testTable2 к вашему файлу #{test.list}. Поскольку значения здесь являются старыми значениями, это будут значения, которые будут отправлены для #{test.list}.

Лучший способ решить эту проблему — использовать один <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>

Код управляемого компонента

//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);
        }
    }
}
person Luiggi Mendoza    schedule 15.12.2012
comment
Спасибо, Луиджи, но это не так, как ты сказал. Я разместил эти три таблицы, чтобы показать различия в поведении p:dataTable и h:dataTable. Но поместите в мой пример только одну из этих таблиц. p:dataTable по-прежнему будет вести себя так, как я описал, и так, как мне не нравится, а h:dataTable будет вести себя так, как мне нравится. Можете ли вы сказать мне, почему p: dataTable берет связанный пустой список из bean-компонента (после очистки), а затем принимает изменения вручную, но не из связанного списка после создания нового списка и обновления p: dataTable? Он запоминает значения, сделанные вручную перед очисткой списка в bean-компоненте. - person robson; 17.12.2012