p:datatable loses sort column and order after ajax refresh

后端 未结 8 1653
攒了一身酷
攒了一身酷 2020-12-17 19:38

I have a button on a page that causes my data table to refresh via an AJAX request. Something like this:




        
8条回答
  •  春和景丽
    2020-12-17 20:10

    Add this PhaseListener to your application and both sorting and filtering will be kept after updating the 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 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;
                        }
                    }
                }
            }
        }
    }
    

    This is for non-lazy data tables. Data tables using a lazy model do not require this, as the lazy model will take care of sorting and filtering. For non-lazy data tables, this should work with both single and multiple column sorting but there is a bug in Primefaces that makes DataTable loose its MultiSortMeta between postbacks when updating the table. This means that the columns selected for sorting before postback are completely lost from FacesContext and component state and cannot be retrieved anymore upon postback. I'll look more into this later and provide an update if I manage to find a workaround or maybe Primefaces will fix it soon.

提交回复
热议问题