Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
p:datatable在ajax刷新后丢失排序列和顺序_Ajax_Sorting_Jsf 2_Primefaces_Datatable - Fatal编程技术网

p:datatable在ajax刷新后丢失排序列和顺序

p:datatable在ajax刷新后丢失排序列和顺序,ajax,sorting,jsf-2,primefaces,datatable,Ajax,Sorting,Jsf 2,Primefaces,Datatable,我在页面上有一个按钮,可以通过AJAX请求刷新数据表。大概是这样的: <h:form id="datatable"> <p:dataTable/> </h:form> <p:commandButton update=":datatable"> <p:dataTable id="myTable" widgetVar="myTableWidget" value="#{myArticles}"

我在页面上有一个按钮,可以通过AJAX请求刷新数据表。大概是这样的:

<h:form id="datatable">
<p:dataTable/>
</h:form>
<p:commandButton update=":datatable">
<p:dataTable id="myTable"
             widgetVar="myTableWidget"
             value="#{myArticles}"
             var="article"
             sortBy="#{article.price}"
             sortOrder="ASCENDING">
    ...

    <p:column id="price" sortBy="#{article.price}">
        <f:facet name="header">
            <h:outputText value="Price" />
        </f:facet>
        <h:outputText value="#{article.price}" />
    </p:column>

</p:dataTable>
<p:commandButton value="refresh" action="#{tableController.refreshPrices}" update="myTable" oncomplete="postAjaxSortTable(myTableWidget)" />

这一切都很好,只是当刷新表时,它会恢复为不排序,同时仍然显示它是基于上一个值排序的。换句话说,标题仍然高亮显示,箭头仍然指向排序方向,但实际上没有执行排序。显然这并不理想

理想情况下,我希望组件在视图状态下保持其排序顺序,然后在AJAX请求期间提交适当的参数(以便正确定义排序)。我缺少一个参数还是什么?还有其他人有这个问题吗

根据我所知,当表需要排序时,它会发布以下选项:

<componentID>_sortDir
<componentID>_sortKey
<componentID>_sorting
<componentID>_updateBody
\u sortDir
_索特基
_分类
_更新库

当我刷新表单时,这不会发生。如果我只是刷新表也不会发生这种情况(我想我可以通过直接更新组件来解决问题)。有没有办法让表格正确刷新?

编辑:

下面发布的解决方案(LazyTable)适用于由LazyDataModel支持的p:dataTable。每次更新/刷新所需表后,都会调用Overridedload方法,并正确处理排序。简单p:dataTable的问题在于,它仅在第一次加载时或单击排序列之后执行预定义的排序。这是简单表的正常行为

那么,对于简单表格,您有哪些可能性:

  • 更新后不要对表进行排序,而是删除排序列,这样最终用户就不会丢失信息。将此添加到更新按钮的操作侦听器或操作方法:

    UIComponent table  = FacesContext.getCurrentInstance().getViewRoot().findComponent(":dataTablesForm:dataTableId");
    table.setValueExpression("sortBy", null);
    
  • 通过脚本手动更新表的排序。这不是最好的解决方案,但primefaces不提供任何客户端函数来“重新调用”表。 基本上,您知道一次只能对一列进行排序,并且该列的.ui状态处于活动状态。您可以在脚本中使用它并在该列上触发两次单击(1.单击-其他排序顺序,2.单击-返回到当前排序顺序)

我知道这不是最好的解决办法,但它很有效。你可以用它作为一个灵感,使事情变得更好

懒散的 IMHO最合适的方法是直接更新所需的组件。例如:

<h:form id="dataTableForm">
  <p:dataTable id="dataTableToUpdate">
    .
    .
    .
  </p:dataTable>
  <p:commandButton value="Refresh" update=":dataTableForm:dataTableToUpdate" />
</h:form>

.
.
.
在这种情况下,它应该可以正常工作(我想这是您的目的): 使用p:dataTable打开.xhtml,对某些列进行排序(保持facelet打开),从另一个.xhtml更新dataTables数据,例如,单击刷新按钮。dataTable应该以正确(以前选择的)排序顺序显示您的附加值-排序是在更新后执行的


希望有帮助

我用toString()方法实现了一个比较器

比较器

public class DefaultComparator implements Comparator {

    @Override
    public int compare(Object o1, Object o2) {
        return o1.toString().compareToIgnoreCase(o2.toString());
    }
}

解决方案是拥有一个对话bean。在这种情况下,p:dataTable刷新表及其条目,而不影响排序顺序。在每行上都有一个p:commandButton的情况下,表刷新也可以正常工作

对话豆:

@Named
@Stateful
@ConversationScoped
public class ItemBean {

    @Inject
    private Conversation conversation;

    private List<Item> items;

    public List<Item> getItems() {
        return this.items;
    }

    public void retrieve() {
        // if it's an Ajax call then avoid retrieving items
        if (FacesContext.getCurrentInstance().isPostback()) {
            return;
        }
        // start a conversation
        if (this.conversation.isTransient()) {
            this.conversation.begin();
        }
        this.items = retrieveItems();
    }
}
@Named
@有状态
@会话范围
公共类ItemBean{
@注入
私人谈话;
私人清单项目;
公共列表getItems(){
归还此物品;
}
公共无效检索(){
//如果是Ajax调用,请避免检索项目
if(FacesContext.getCurrentInstance().isPostback()){
返回;
}
//开始对话
if(this.conversation.isTransient()){
这个.conversation.begin();
}
this.items=retrieveItems();
}
}
关联页面:

<f:metadata>
    <f:event type="preRenderView" listener="#{itemBean.retrieve}" />
</f:metadata>

<h:form id="form">
    <p:dataTable id="table" var="_item" value="#{testBean.items}">
    ... <!-- you can have the p:commandButton in a column too, to refresh the respective column only
        <p:commandButton value="Refresh" action="#{itemBean.update(_item)}" 
        -->
    </p:dataTable> 
    <p:commandButton value="Refresh" action="#{itemBean.update}" update=":form:table"/>
</h:form>

... 

首先,上有一个未解决的问题,它针对这个问题,但最近被标记为“不会解决”

尽管如此,我还是找到了一个不错的解决办法。PrimeFaces表的排序可以通过调用datatable小部件上未记录的JavaScript方法来触发。以下内容可能不适用于PrimeFaces的未来版本,但适用于3.4.2:

只需将以下内容添加到组件中,即可触发更新:

oncomplete="myTableWidget.sort($(PrimeFaces.escapeClientId('#{p:component('sortColumnId')}')), 'ASCENDING')"
该表可能如下所示:

<h:form id="datatable">
<p:dataTable/>
</h:form>
<p:commandButton update=":datatable">
<p:dataTable id="myTable"
             widgetVar="myTableWidget"
             value="#{myArticles}"
             var="article"
             sortBy="#{article.price}"
             sortOrder="ASCENDING">
    ...

    <p:column id="price" sortBy="#{article.price}">
        <f:facet name="header">
            <h:outputText value="Price" />
        </f:facet>
        <h:outputText value="#{article.price}" />
    </p:column>

</p:dataTable>
<p:commandButton value="refresh" action="#{tableController.refreshPrices}" update="myTable" oncomplete="postAjaxSortTable(myTableWidget)" />

...
所以更新表可以像这样工作

<p:commandButton value="refresh" action="#{tableController.refreshPrices}" update="myTable" oncomplete="myTableWidget.sort($(PrimeFaces.escapeClientId('#{p:component('price')}')), 'ASCENDING')" />

我为@truemmer的解决方案编写了一个扩展。His将排序顺序恢复为默认顺序,而我的排序顺序将恢复为用户选择的上一个排序顺序

function postAjaxSortTable(datatable)
{
    var selectedColumn = datatable.jq.find('.ui-state-active');
    if(selectedColumn.length <= 0)
    {
        return;
    }
    var sortorder = "ASCENDING";
    if(selectedColumn.find('.ui-icon-triangle-1-s').length > 0)
    {
        sortorder = "DESCENDING";
    }
    datatable.sort(selectedColumn, sortorder);
}
函数postAjaxSortTable(datatable)
{
var selectedColumn=datatable.jq.find('.ui state active');
如果(selectedColumn.length 0)
{
sortorder=“下降”;
}
datatable.sort(selectedColumn、sortorder);
}
更新与TrueMer相同的表的工作方式如下:

<h:form id="datatable">
<p:dataTable/>
</h:form>
<p:commandButton update=":datatable">
<p:dataTable id="myTable"
             widgetVar="myTableWidget"
             value="#{myArticles}"
             var="article"
             sortBy="#{article.price}"
             sortOrder="ASCENDING">
    ...

    <p:column id="price" sortBy="#{article.price}">
        <f:facet name="header">
            <h:outputText value="Price" />
        </f:facet>
        <h:outputText value="#{article.price}" />
    </p:column>

</p:dataTable>
<p:commandButton value="refresh" action="#{tableController.refreshPrices}" update="myTable" oncomplete="postAjaxSortTable(myTableWidget)" />

编辑:Primefaces 4.0多端口支持

function postAjaxSortTable(datatable) {
    var selectedColumn = undefined;

    // multisort support
    if(datatable && datatable.cfg.multiSort) {
        if(datatable.sortMeta.length > 0) {
            var lastSort = datatable.sortMeta[datatable.sortMeta.length-1];
            selectedColumn = $(document.getElementById(lastSort.col));
        }
    } else {
        selectedColumn = datatable.jq.find('.ui-state-active');
    }

    // no sorting selected -> quit
    if(!selectedColumn || selectedColumn.length <= 0) {
        return;
    }

    var sortorder = selectedColumn.data('sortorder')||"DESCENDING";
    datatable.sort(selectedColumn, sortorder, datatable.cfg.multiSort);
}
函数postAjaxSortTable(datatable){
var selectedColumn=未定义;
//多端口支持
if(datatable&&datatable.cfg.multiSort){
如果(datatable.sortMeta.length>0){
var lastSort=datatable.sortMeta[datatable.sortMeta.length-1];
selectedColumn=$(document.getElementById(lastSort.col));
}
}否则{
selectedColumn=datatable.jq.find('.ui-state-active');
}
//未选择排序->退出

如果(!selectedColumn | | selectedColumn.length我与您有相同的问题。我能够使用解决问题。由于,我需要添加额外的实用工具LazyDataModel(请参阅行索引注释):


将此PhaseListener添加到应用程序中,在更新DataTable后,将保留排序和筛选

public class DataTableUpdatePhaseListener implements PhaseListener {

    private static final long serialVersionUID = 1L;

    @Override
    public void afterPhase(PhaseEvent event) {
        // Nothing to do here
    }

    @Override
    public void beforePhase(PhaseEvent event) {
        FacesContext facesContext = event.getFacesContext();
        if (!facesContext.isPostback()) {
            return;
        }

        PartialViewContext partialViewContext = facesContext.getPartialViewContext();
        if (partialViewContext != null) {
            Collection<String> renderIds = partialViewContext.getRenderIds();

            for (String renderId : renderIds) {
                UIComponent component = facesContext.getViewRoot().findComponent(renderId);
                if (component instanceof DataTable) {
                    DataTable table = (DataTable) component;
                    if (!table.isLazy()) {
                        updateDataTable(table);
                    }
                }
            }
        }
    }

    @Override
    public PhaseId getPhaseId() {
        return PhaseId.RENDER_RESPONSE;
    }

    private void updateDataTable(DataTable table) {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext == null || table == null) {
            return;
        }

        // Reapply filtering
        if (!table.getFilters().isEmpty()) {
            FilterFeature filterFeature = new FilterFeature();
            filterFeature.decode(facesContext, table);
        } else {
            table.setFilteredValue(null);
        }

        // Reapply sorting
        ValueExpression tableSortByVE = table.getValueExpression("sortBy");
        if (tableSortByVE != null) {
            String tableSortByExpression = tableSortByVE.getExpressionString();

            // Loop on children, that are the columns, to find the one whose order must be applied.
            for (UIComponent child : table.getChildren()) {
                Column column = (Column) child;
                ValueExpression columnSortByVe = column.getValueExpression("sortBy");
                if (columnSortByVe != null) {
                    String columnSortByExpression = columnSortByVe.getExpressionString();

                    if (tableSortByExpression != null && tableSortByExpression.equals(columnSortByExpression)) {
                        // Now sort table content
                        SortFeature sortFeature = new SortFeature();
                        sortFeature.sort(facesContext, table, tableSortByVE,
                                SortOrder.valueOf(table.getSortOrder().toUpperCase(Locale.ENGLISH)),
                                table.getSortFunction());

                        break;
                    }
                }
            }
        }
    }
}
公共类DataTableUpdateFaseListener实现PhaseL
public void preRenderViewListener() {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (!facesContext.isPostback()) {
        return;
    }

    PartialViewContext partialViewContext = facesContext.getPartialViewContext();
    if (partialViewContext != null) {
        Collection<String> renderIds = partialViewContext.getRenderIds();

        for (String renderId : renderIds) {
            UIComponent component = facesContext.getViewRoot().findComponent(renderId);
            if (component instanceof DataTable) {
                DataTable table = (DataTable) component;
                if (!table.isLazy()) {
                    updateDataTable(table);
                }
            }
        }
    }
}

private void updateDataTable(DataTable table) {
    FacesContext facesContext = FacesContext.getCurrentInstance();
    if (facesContext == null || table == null) {
        return;
    }
    if (!table.getFilters().isEmpty()) {
        FilterFeature filterFeature = new FilterFeature();
        filterFeature.decode(facesContext, table);
    } else {
        table.setFilteredValue(null);
    }
    ValueExpression tableSortByVE = table.getValueExpression("sortBy");
    if (tableSortByVE != null) {
        String tableSortByExpression = tableSortByVE.getExpressionString();
        for (UIComponent child : table.getChildren()) {
            Column column = (Column) child;
            ValueExpression columnSortByVe = column.getValueExpression("sortBy");
            if (columnSortByVe != null) {
                String columnSortByExpression = columnSortByVe.getExpressionString();
                if (tableSortByExpression != null && tableSortByExpression.equals(columnSortByExpression)) {
                    SortFeature sortFeature = new SortFeature();
                    sortFeature.sort(facesContext, table, tableSortByVE, table.getVar(),
                            SortOrder.valueOf(table.getSortOrder().toUpperCase(Locale.ENGLISH)),
                            table.getSortFunction());
                    break;
                }
            }
        }
    }
}