Maxi
Maxi

Reputation: 443

Filter a lazy dataTable with dynamic columns

I have a dataTable with dynamic Columns:

<p:dataTable id="bookings" var="booking" value="#{tableBean.dataModel}" 
    widgetVar="bookingTable" filteredValue="#{tableBean.filteredFields}"
    paginator="true" rows="15"
    lazy="true" rowsPerPageTemplate="15,30,50" type="none" draggableColumns="true">

[...]

<p:columns value="#{tableBean.columns}" var="column" columnIndexVar="colIndex"
           sortBy="#{booking.properties[column.property]}"
           filterBy="#{booking.properties[column.property]}"
           filterMatchMode="in"
           styleClass="telegrotesk">
    <f:facet name="header">
        <h:outputText value="#{column.header}"/>
    </f:facet>
    <f:facet name="filter">
        <p:selectCheckboxMenu label="#{column.header}" onchange="PF('bookingTable').filter()">
            <f:selectItems value="#{column.possibilities}" />
        </p:selectCheckboxMenu>
    </f:facet>
    <h:outputText value="#{booking.properties[column.property]}"/>
</p:columns>

column is similar like in the primefaces example (http://www.primefaces.org/showcase/ui/data/datatable/filter.xhtml) this class:

static public class ColumnModel implements Serializable {

    private String header;
    private String property;
    private List<SelectItem> possibilities;

    public ColumnModel(Field property) {
        this.header = property.getName();
        this.property = property.getSqlName();
    }

    public String getHeader() {
        return header;
    }

    public String getProperty() {
        return property;
    }

    public List getPossibilities() {
        return possibilities;
    }

    public void setPossibilities(List<SelectItem> possibilities) {
        this.possibilities = possibilities;
    }
}

In my example there is for testing only one dynamic column, that shows the User that created a booking. It works, that in the checkboxdropdown are shown all users. When I select one or more users, the function load

public List<Booking> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
    [...]
}

is executed, but filters is always empty!

The list possibilities in the ColumnModel is a Collection of SelectItems. The label is always the username, the value the User object. For the user class I defined a Converter class implementing javax.faces.convert.Converter with the @FacesConverter(forClass = User.class)

What am I doing wrong that the filter map is always empty?

EDIT

When I do it like this

<p:columns value="#{tableBean.columns}" var="column" columnIndexVar="colIndex"
           sortBy="#{booking.properties[column.property]}"
           filterBy="#{booking.properties[column.property]}"
           filterMatchMode="in"
           filterOptions="#{column.possibilities}"
           styleClass="telegrotesk">

and with no facet it works correctly but I can only select one User.

I'm using primefaces 5.0, jsf 2.2.1 and glassfish v4

Upvotes: 2

Views: 8455

Answers (2)

Bipin
Bipin

Reputation: 51

yes it's possible to do filter options in dynamic columns in primefaces 4.0 version

<p:columns value="#{pc_searchJobBean.columns}" var="column"
                                            id="searchJobColumns" columnIndexVar="colIndex"
                                            rendered="#{column.property eq 'minWorkExp' or column.property eq 'maxWorkExp' or column.property eq 'minSalary'
                                            or column.property eq 'maxSalary'}"
                                            filterBy="#{tbl[column.property]}" filterOptions="#{column.items}">

                                            <f:facet name="header">
                                                <h:outputText value="#{column.header}" escape="false">
                                                </h:outputText>
                                            </f:facet>

                                            <h:outputText value="#{tbl[column.property]}" escape="false"
                                                rendered="#{column.header!='Priority'}">
                                                <f:convertDateTime
                                                    pattern="#{userSettingBean.userSettingVO.dateFormat}" />
                                            </h:outputText>

                                        </p:columns>

Java code...

public static class ColumnModel {

        private String header;
        private String property;
        private SelectItem[] items;

        public ColumnModel(String header, String property, SelectItem[] items) {
            super();
            this.header = header;
            this.property = property;
            this.setItems(items);
        }

        public ColumnModel(String header, String property) {
            this.header = header;
            this.property = property;
        }

        public String getHeader() {
            return header;
        }

        public void setHeader(String header) {
            this.header = header;
        }

        public String getProperty() {
            return property;
        }

        public void setProperty(String property) {
            this.property = property;
        }

        public SelectItem[] getItems() {
            return items;
        }

        public void setItems(SelectItem[] items) {
            this.items = items;
        }
    }

Set selectItems in columns

if(model.getProperty().equals("country")){
                    model.setItems(countryOptions);
                }if(model.getProperty().equals("jobType")){
                    model.setItems(jobTypeOptions);
                }

Upvotes: 1

Max
Max

Reputation: 1157

You did nothing wrong, this is a Primefaces bug.

Please star it, let's try and get it fixed.

New PF5 enhanced filtering does not work with Dynamic Columns: https://code.google.com/p/primefaces/issues/detail?id=6912

Workaround:

Step 1: In the Primefaces source (https://code.google.com/p/primefaces/source/checkout) open FilterFeature.java.

In the populateFilterMetaData(FacesContext context, DataTable table) method, around line 300, replace:

filterId = dynamicColumn.getContainerClientId(context) + separator + "filter";
dynamicColumn.cleanStatelessModel();

with this:

filterId = dynamicColumn.getContainerClientId(context) + separator + "filter";
filterFacet = null;
dynamicColumn.cleanStatelessModel();

So basically you just add filterFacet = null;

Tips for building PF: https://code.google.com/p/primefaces/wiki/BuildingFromSource

Step 2: In your project, ensure that your input component in the filter facet has an id of filter

Example:

<f:facet name="filter">
    <p:selectOneButton id="filter" onchange="PF('recordTable').filter()" >
        <f:converter converterId="javax.faces.Boolean" />
        <f:selectItem itemLabel="All" itemValue="" />
        <f:selectItem itemLabel="True" itemValue="true" />
        <f:selectItem itemLabel="False" itemValue="false" />
    </p:selectOneButton>
</f:facet>

Upvotes: 1

Related Questions