单元格editMode中的JSF Primefaces数据表不将已编辑的值发送到托管bean

时间:2014-07-17 19:41:51

标签: jsf primefaces

我有两个primefaces dataTables。第一个显示MainEntity的实例。 第二个显示与第一个数据表上所选MainEntity关联的单词列表(只是字符串)。

版画屏幕说明了我的意思。

我的问题是,当我在Word列表中编辑字符串时,我的侦听器方法将不会收到新值。事实上,当我调用event.getNewValue()方法时,我会得到旧值。

我错过了什么?

我正在使用JavaServer Faces 2.2,Primefaces 5.0和Spring Framework 4.0.3。

提前感谢您的帮助。

xhtml,托管bean和MainEntity的代码如下:

  

mainEntity.xhtml:

<h:body>
    <h:form id="mainEntityForm">
        <p:panelGrid columns="1" fullPage="true" id="dashboard">
            <f:facet name="header">
                <h2>MainEntity Table</h2>
            </f:facet>
            <p:panel>
                <f:facet name="header">
                    MainEntity List
                    <p:commandButton value="New MainEntity"
                        actionListener="#{mainEntityController.createMainEntityDialog}"
                        styleClass="header-button">
                        <p:ajax event="dialogReturn" update=":mainEntityForm:mainEntityTable" />
                    </p:commandButton>
                </f:facet>
                <p:dataTable id="mainEntityTable" var="mainEntity" value="#{mainEntityController.mainEntities}"
                    editable="true" editMode="cell" widgetVar="cellMainEntity"
                    selectionMode="single" selection="#{mainEntityController.selectedMainEntity}"
                    rowKey="#{mainEntity.id}" tableStyle="width:auto">

                    <p:ajax event="rowSelect" update=":mainEntityForm:stringGrid :mainEntityForm:entityAGrid :mainEntityForm:entityBGrid" />
                    <p:ajax event="cellEdit" listener="#{mainEntityController.onEditMainEntity}" update=":mainEntityForm:mainEntityTable" />

                    <p:column headerText="ID">
                        <h:outputText value="#{mainEntity.id}" />
                    </p:column>
                    <p:column headerText="Name">
                        <p:cellEditor>
                            <f:facet name="output">
                                <h:outputText id="nameOutput" value="#{mainEntity.name}" />
                            </f:facet>
                            <f:facet name="input">
                                <h:inputText id="atyInput" value="#{mainEntity.qty}" />
                            </f:facet>
                        </p:cellEditor>
                    </p:column>
                    <p:column headerText="Commands">
                        <p:commandButton title="Remove MainEntity" icon="ui-icon-trash"
                            actionListener="#{mainEntityController.deleteMainEntity(mainEntity)}"
                            update=":mainEntityForm:mainEntityTable" />
                    </p:column>
                </p:dataTable>
            </p:panel>
            <p:panelGrid fullPage="true" id="mainEntityDetail">
                <f:facet name="header">
                    <p:row>
                        <p:column colspan="4">
                            <h2>MainEntity Detail</h2>
                        </p:column>
                    </p:row>
                </f:facet>
                <p:row>
                    <p:column>
                        <p:panel>
                            <f:facet name="header">
                                Word List
                                <p:commandButton value="New Word"
                                        actionListener="#{mainEntityController.addNewWord()}"
                                        styleClass="header-button"
                                        update=":mainEntityForm:wordGrid">
                                </p:commandButton>
                            </f:facet>
                            <p:dataTable id="wordGrid" var="word"
                                value="#{mainEntityController.selectedMainEntity.wordList}"
                                tableStyle="width:auto" editable="true" editMode="cell" widgetVar="cellWord">

                                <p:ajax event="cellEdit" listener="#{mainEntityController.onEditWord}" />

                                <p:column headerText="Word">
                                    <p:cellEditor>
                                        <f:facet name="output">
                                            <h:outputText id="wordOutput" value="#{word}" />
                                        </f:facet>
                                        <f:facet name="input">
                                            <h:inputText id="wordInput" value="#{word}" />
                                        </f:facet>
                                    </p:cellEditor>
                                </p:column>
                                <p:column headerText="Commands">
                                    <p:commandButton title="Remove Word"
                                        icon="ui-icon-trash"
                                        actionListener="#{mainEntityController.removeWord(word)}"
                                        update=":mainEntityForm:wordGrid" />
                                </p:column>
                            </p:dataTable>
                        </p:panel>
                    </p:column>
                </p:row>
            </p:panelGrid>
        </p:panelGrid>
    </h:form>
</h:body>
  

MainEntityController.java(托管bean):

@ManagedBean
@SessionScoped
public class MainEntityController {

    //...

    private MainEntity selectedMainEntity;

    public List<MainEntity> mainEntities;

    //...

    public MainEntity getSelectedMainEntity(){
        return selectedMainEntity;
    }

    public void setSelectedMainEntity(MainEntity mainEntity){
        this.selectedMainEntity = mainEntity;
    }

    //...

    public void onEditWord(CellEditEvent event) {
        Object oldValue = event.getOldValue();
        Object newValue = event.getNewValue();

        if(newValue != null && !newValue.equals(oldValue)) {

            // THE PROBLEM IS HERE
            // I NEVER ACTUALLY REACH THIS CODE
            // newValue is always equal to oldValue!

            FacesContext context = FacesContext.getCurrentInstance();
            String word = context.getApplication().evaluateExpressionGet(context, "#{word}", String.class);
            System.out.println(newValue);
            System.out.println(word);

            FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Word Changed", "Old: " + oldValue + ", New:" + newValue);
            FacesContext.getCurrentInstance().addMessage(null, msg);
        }
    }
}
  

MainEntity.java:

@Entity
public class MainEntity {

    @Id
    private String id;

    @ElementCollection(fetch=FetchType.EAGER)
    @CollectionTable(
                name="MainEntity_Word",
                joinColumns = @JoinColumn(name = "id", referencedColumnName="id")
            )
    @Column(name = "word")
    private Set<String> wordList;

    //...

    public void addWord(String word) {
        this.wordList.add(word);
    }

    public void removeWord(String word) {
        this.wordList.remove(word);
    }

    public Set<String> getWordList() {
        return wordList;
    }

    public void setWordList(Set<String> wordList) {
        this.wordList = wordList;
    }
}

2 个答案:

答案 0 :(得分:0)

更改

<h:inputText id="wordInput" value="#{word}" />

<p:inputText id="wordInput" value="#{word}" />

<h:inputText id="wordInput" value="#{word}" >
<p:ajax event="change" process="@this"/>
</h:inputText>

您需要 ajaxify 输入组件,最后更新outputText组件。

<强>被修改

更改此栏:

<p:column headerText="Word" >
<p:cellEditor>
<f:facet name="output">
<h:outputText id="wordOutput" value="#{word}" />
</f:facet>
<f:facet name="input">
<h:inputText id="wordInput" value="#{word}" />
</f:facet>
</p:cellEditor>
</p:column>

<p:column headerText="Word" >
<p:cellEditor>
<f:facet name="output">
<h:outputText id="wordOutput" value="#{word}" />
</f:facet>
<f:facet name="input">
<p:inputText id="wordInput" value="#{word}" >
<p:ajax event="change" update="wordOutput" />
</p:inputText>
</f:facet>
</p:cellEditor>
</p:column>

编辑2

来自Chapter 24 Introduction to the Java Persistence API

  

如果实体实例按值传递为分离对象,例如   通过会话bean的远程业务接口,该类必须   实现Serializable接口。

答案 1 :(得分:0)

我终于明白了。

我怀疑字符串是不可变的,我所做的就是封装“&#39;字”。在类如下的类中:

public class Word {
    private String word;

    Word (String word) {
        this.setWord(word);
    }

    public String getWord() {
        return this.word;
    }

    public void setWord(String word) {
        this.word = word;
    }
}

之后,我还必须在托管bean(控制器)中创建一个集来保存一组单词,比如&#39; private Set managedWordList;&#39;。

我还更改了托管bean内部列表的getter,将String set转换为Word集:

public Set<Word> getWordList() {
    if (this.selectedMainEntity != null){
        this.wordList = new HashSet<Word>();
        for (String word : this.selectedMainEntity.getWordList()) {
            this.wordList.add(new Word(word));
        }
    }
    return this.wordList;
}

最后,我更改了dataTable以引用新集。从:

<p:dataTable ... value="#{mainEntityController.selectedMainEntity.wordList}"... />

要:

<p:dataTable ... value="#{mainEntityController.wordList}"... />

只有这样我才能按照我的预期工作。