jsf - 监听器排序后 PrimeFaces DataTable 渲染列表错误(bug?)

标签 jsf primefaces jsf-2.2

DataTable 确实刷新,但未正确呈现列表。 (JSF 2.2、Mojarra 2.2.0、PrimeFaces 5.2)

我在 PrimeFaces DataTable 中有一个日期列表,每次用户添加或编辑日期时我都会重新排序。这几乎可以完美地工作。请帮我看看我做错了什么,或者让我知道我发现了一个错误。 (请注意,它不是 update 目标,因为我尝试使用 update="@all" ,但它没有改变任何内容。)

使用下面的代码尝试一下:

1) 添加 11/21/2015,然后添加 11/20/2015。请注意,它在 onAdd 上对它们进行了重新排序。

enter image description here

控制台:

onAdd, after
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015]
DataTableEntry[Date:Sat Nov 21 00:00:00 EST 2015]

2) 然后编辑 11/21/2015 将其更改为 11/19/2015。请注意,编辑过的那个已经消失了,现在有两个 20。 错误?!?

enter image description here

控制台:

onRowEdit, before
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015]
DataTableEntry[Date:Thu Nov 19 00:00:00 EST 2015]
onRowEdit, after
DataTableEntry[Date:Thu Nov 19 00:00:00 EST 2015]
DataTableEntry[Date:Fri Nov 20 00:00:00 EST 2015]

3)然后点击我的“刷新页面”命令按钮。现在可以正确显示。

enter image description here

无论其之前/之间/之后的位置如何,添加日期都不会出现问题。我发现你可以编辑日期,只要它实际上不改变顺序,它就可以正常工作。顺序一改变,编辑过的那个就会消失,旁边的一个会在视觉上被复制到原来的位置。

数据表排序.xhtml

<!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:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    >
<h:head>
    <title><ui:insert name="title">DataTable</ui:insert></title>
</h:head>

<h:body>
    <h:form id="modelerForm">
        <p:commandButton value="Refresh page" ajax="false"/>

        <h:outputLabel for="date" value="Date"/>
        <h:panelGroup>
            <p:calendar id="date" pattern="MM/dd/yyyy" placeholder="mm/dd/yyyy" mask="true" showOn="button" navigator="true"/>
            <h:commandButton value="Add">
                <f:ajax event="action" listener="#{dataTableBean.onAdd}" execute="date" render="entries"/>
            </h:commandButton>
        </h:panelGroup>

        <p:dataTable id="entries" value="#{dataTableBean.entries}" var="entry" emptyMessage="No dates added" editable="true" tableStyle="width:auto">
            <p:ajax event="rowEdit" listener="#{dataTableBean.onRowEdit}" update="entries"/>
            <p:column headerText="Dates">
                <p:cellEditor>
                    <f:facet name="output">
                        <h:outputText value="#{entry.date}">
                            <f:convertDateTime pattern="MM/dd/yyyy" />
                        </h:outputText>
                    </f:facet>
                    <f:facet name="input">
                        <p:calendar id="date" value="#{entry.date}" pattern="MM/dd/yyyy" placeholder="mm/dd/yyyy" mask="true" showOn="button" navigator="true"/>
                    </f:facet>
                </p:cellEditor>
            </p:column>
            <p:column>
                <p:rowEditor/>
            </p:column>
            <p:column>
                <p:commandLink title="Remove date">
                    <h:outputText value="" styleClass="ui-icon ui-icon-trash"/>
                    <f:ajax event="click" listener="#{dataTableBean.entries.remove(entry)}" render="entries"/>
                </p:commandLink>
            </p:column>
        </p:dataTable>
    </h:form>
</h:body>
</html>

DataTableBean.java

package com.aadhoc.test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.event.AjaxBehaviorEvent;

import org.primefaces.component.datatable.DataTable;
import org.primefaces.event.RowEditEvent;

@ManagedBean(name="dataTableBean")
@SessionScoped
public class DataTableBean {

    private List<DataTableEntry> entries = new ArrayList<>();
    public List<DataTableEntry> getEntries() {
        return entries;
    }
    public void setEntries(List<DataTableEntry> entries) {
        this.entries = entries;
    }   

    public void onAdd(AjaxBehaviorEvent event) {
        DumpList("onAdd, before");

        UIComponent component = event.getComponent();
        UIComponent dateComp = component.findComponent("date");
        Date date = (Date) ((UIInput)dateComp).getValue();
        DataTableEntry entry = new DataTableEntry();
        entry.setDate(date);
        getEntries().add(entry);

        sortEntries(getEntries());
        DumpList("onAdd, after");
    }

    public void onRowEdit(RowEditEvent event) {
        DumpList("onRowEdit, before");

        // Get entries via DataTable#getValue because in real code
        // I don't have direct access to entries.
        DataTable dt = (DataTable) event.getSource();
        @SuppressWarnings("unchecked")
        List<DataTableEntry> entries = (List<DataTableEntry>) dt.getValue();
        sortEntries(entries);

        DumpList("onRowEdit, after");
    }

    private void DumpList(String msg) {
        System.out.println(msg);
        for (DataTableEntry entry : entries) {
            System.out.println(entry);
        }
    }

    private <T> void sortEntries(List<DataTableEntry> entries) {
        entries.sort(new Comparator<DataTableEntry>() {
            @Override
            public int compare(DataTableEntry entry1, DataTableEntry entry2) {
                return entry1.getDate().compareTo(entry2.getDate());
            }
        });
    }
}

DataTableEntry.java

package com.aadhoc.test;

import java.io.Serializable;
import java.util.Date;

public class DataTableEntry implements Serializable {
    private static final long serialVersionUID = -2513940455250513641L;
    private Date date;
    public Date getDate() {
        return date;
    }
    public void setDate(Date date) {
        this.date = date;
    }

    public String toString() {
        return getClass().getSimpleName()+"[Date:"+getDate()+"]";
    }
}

最佳答案

我遇到了同样的问题。

解决方法:在 <p:dataTable widgetVar="datatableVar" ...> 中定义 widgetVar 属性并将此行添加到 onRowEdit 函数的末尾:

RequestContext.getCurrentInstance().execute("PF('datatableVar').filter()");

这将强制渲染整个数据表。

关于jsf - 监听器排序后 PrimeFaces DataTable 渲染列表错误(bug?),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33527471/

相关文章:

jsf - 使用 "Please select"f :selectItem with null/empty value inside a p:selectOneMenu

dialog - 使 p :dialog scrollable when working with maximizable

jsf - ui :repeat in jsf 中的输入绑定(bind)

jsf - 重定向如果 f :viewParam is empty

java - JSF 2 使用 @ManagedProperty 注入(inject) Spring bean/service 而没有 xml

apache - 没有/faces/无法访问 JSF2 应用程序

jsf - 在 Primefaces 中的不同布局单元之间拖放

javascript - 如何使用目标 div 中的数据属性作为 PrimeFaces ContextMenu 结果中的 View 参数

xml - 在 JSF 中读写 XML 文件

javascript - 手动触发更改事件