完成<p:ajax event =“cellEdit”> </p:ajax> </p:datatable>时更新整个<p:datatable>

时间:2013-10-23 17:48:44

标签: jsf primefaces datatable celleditorlistener

编辑单元格后,我无法重新渲染PrimeFaces数据表。更改一个单元格中的值可能会更改其他单元格中的条目,因此需要刷新整个表格。

这是JSF页面:

<h:form id="testForm">
    <p:outputPanel id="testContainer">

        <p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">

            <p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />

            <p:column headerText="Col1">  
                <p:cellEditor>
                    <f:facet name="output"><h:outputText value="#{entry.col1}" /></f:facet>
                    <f:facet name="input"><p:inputText value="#{entry.col1}" /></f:facet>
                </p:cellEditor> 
            </p:column>

            <p:column headerText="Col2">
                <p:cellEditor>
                    <f:facet name="output"><h:outputText value="#{entry.col2}" /></f:facet>
                    <f:facet name="input"><p:inputText value="#{entry.col2}" /></f:facet>
                </p:cellEditor>  
            </p:column>

        </p:dataTable>

        <p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />

    </p:outputPanel>                                    
</h:form>

这是支持bean:

@ManagedBean(name = "tableBean", eager = false)
@ViewScoped 
public class TableBean {

    public TableBean() {
        RowData entry = new RowData("a1", "b1");
        entries.add(entry);
        entry = new RowData("a2", "b2");
        entries.add(entry);
        entry = new RowData("a3", "b3");
        entries.add(entry);
    }

    public class RowData {

        private String col1;
        private String col2;

        public RowData(String col1, String col2) {
            this.col1 = col1;
            this.col2 = col2;
        }

        public String getCol1() {
            return col1;
        }

        public void setCol1(String col1) {
            this.col1 = col1;
        }

        public String getCol2() {
            return col2;
        }

        public void setCol2(String col2) {
            this.col2 = col2;
        }
    }

    private ArrayList<RowData> entries = new ArrayList<RowData>();

    public List<RowData> getData() {
        return entries;
    }

    public void onCellEdit(CellEditEvent event) {
        entries.get(event.getRowIndex()).setCol1("Dummy Col 1");
        entries.get(event.getRowIndex()).setCol2("Dummy Col 2");        
    }   
}

在cellEdit AJAX事件中包含update =“:testForm:testContainer”时,更改单元格值会删除屏幕上的数据表并仅呈现单元格内容(以及按钮) - 我不明白为什么会这样。如果未指定update属性,则表格将保留在屏幕上且活动单元格已更新,但其他单元格均未更新(如预期的那样)。

通过在AJAX cellEdit事件中不指定update属性并在编辑单元格的值后单击Redisplay按钮,可以实现所需的行为(以非自动方式)。我怎样才能以自动方式实现这一点,为什么更新属性不能像我期望的那样工作?

我正在使用PrimeFaces 4.0。

6 个答案:

答案 0 :(得分:56)

rowEditcellEdit事件在表内设计时不会更新/重新呈现除当前行之外的任何内容,即使在update属性中明确指定时也是如此。这是PrimeFaces有点过分热衷于尽量减少响应大小的结果。在大多数情况下这是有道理的,但在具体情况下并非如此。值得一个问题报告。

同时,在他们修复此行为之前,最好的办法是使用<p:remoteCommand>调用所需的侦听器方法并执行表的完整更新。

重写

<p:dataTable ...>
    <p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />
    ...
</p:dataTable>

<p:remoteCommand name="onCellEdit" action="#{tableBean.onCellEdit}" update="testContainer" />
<p:dataTable ...>
    <p:ajax event="cellEdit" oncomplete="onCellEdit()" />
    ...
</p:dataTable>

答案 1 :(得分:20)

BaLusC解决方案并没有直接为我工作。 onCellEdit需要一个CellEditEvent作为参数。我的解决方法如下:

<p:remoteCommand name="onCellEdit" update="testContainer" />
<p:dataTable ...>
    <p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" oncomplete="onCellEdit()" />
    ...
</p:dataTable>

答案 2 :(得分:5)

如果没有一个解决方案适合你,这对我有用

<p:dataTable ... id="theId" widgetVar="theWidget" ...>
                <p:ajax event="rowEdit" listener="#{...}"
                        oncomplete="PF('theWidget').filter()"/> 
....

我在ajax完成的PF小部件上调用过滤器方法,任何执行&#34;重新加载&#34;的方法。该表应该有效,我使用过滤器,因为我的表有列过滤器。

答案 3 :(得分:0)

我测试了你的代码。首先,我将p:commandButton移出p:outputPanel。这是修改后的代码:

<h:form id="testForm">
            <p:outputPanel id="testContainer">

                <p:dataTable id="testTable" value="#{tableBean.data}" var="entry" editable="true" editMode="cell">

                    <p:ajax event="cellEdit" listener="#{tableBean.onCellEdit}" update=":testForm:testContainer" />

                    (...)

                </p:dataTable>
            </p:outputPanel>
            <p:commandButton id="refreshButton" value="Redisplay" update="testContainer" />
        </h:form>

我认为此代码无法正常运行。如果您在表中更改任何内容,则每次渲染完整表时都会显示p:ajax。因此,程序从TableBean构造函数加载基本数据并删除新数据。

basic data

如果我省略了你的p:ajax代码,那么屏幕上的任何新数据都不会消失。 refreshButton p:commandButton正常工作。

  

在cellEdit中包含update =“:testForm:testContainer”时   AJAX事件,更改单元格值会删除屏幕上的数据表   只渲染单元格内容(以及按钮) - 我没有   明白为什么会这样。

我认为将设置添加update=":testForm:testContainer"给ajax是不好的,因为它更新了你的outputPanel而不是exepted(第一次正常工作,第二次无法编辑单元格,因为程序更新到很多次表) 。

我不知道你的目标是什么。如果你想要没有commandButton的渲染表,那么你可以指定一个javascript事件或p:消息,这就消失了你可以渲染表。

我认为如果省略p:ajax中的更新或指定更新一个p:消息,并将p.commandButton移出testContainer,则代码开始正常工作。

答案 4 :(得分:0)

5年后,此问题仍然存在。不幸的是,尽管ltlBeBoy在其评论中已经指出,尽管Baukes解决方案非常有用并且包含重要的见解,但它仍然不完整。后续的没有更改的编辑将导致表状态不一致,无法再进行编辑。原因是jn远程更新是在新单元格的编辑模式已激活之后进行的。因此,新单元格的编辑模式将被更新破坏。但是,无法在Ajax侦听器oncomplete中进行更新,因为这将错误地仅在一个单元格中显示表。

解决方案是仅在发生更改时才在远程命令侦听器中执行更新。因此,在tableBean#onCellEdit中,您将实现程序化更新,远程侦听器和指示更改的标志:

tableBean

远程命令不再具有更新属性:

public static void update(String id) {
   PrimeFaces pf = PrimeFaces.current(); //RequestContext.getCurrentInstance() for <PF 6.2
   if(pf.isAjaxRequest()) pf.ajax().update(id);
}

/** Whether onCellEdit changed the value */
boolean onCellEditChange;

public void onCellEditRemote() { 
    if(!onCellEditChange) update("testContainer");
}

public void onCellEdit(CellEditEvent event) {
    ...  onCellEditChange= /*Change happend*/ ...
}

答案 5 :(得分:0)

尝试使用流程

...