Search code examples
javascriptjqueryjsfprimefacesprimefaces-datatable

How to save and restore filter state of primefaces datatable with costum filter (selectCheckboxMenu) via javascript?


I have a primefaces datatable and want to filter it with a selectCheckboxMenu

<p:column filterBy="#{entity.category}" headerText="Category" filterMatchMode="in">

    <f:facet name="filter">
        <p:selectCheckboxMenu label="Category" onchange="PF('datatable').filter()">
            <f:selectItems value="#{bean.categoryOptions}"/>
        </p:selectCheckboxMenu>
    </f:facet>

    <h:outputText value="#{entity.category}" />
</p:column>

The filter itself works well. I can filter the datatable and after a reload of the site only the filtered values are there too.

My problem is that after a reload the filter state of the datatable is gone. I see that the filter worked but i don't see the value of the filter in the header of the datatable.

The form with the datatable:

<h:form id="form">
    <p:dataTable var="entity" value="#{bean.list}" widgetVar="datatable" filterEvent="enter" id="datatable"
        lazy="true">

        <p:ajax event="filter" process=":form:filters"
            onstart="saveDatatableState()"></p:ajax>

        ... columns ...

    </p:dataTable>

    <h:inputHidden id="filters" value="#{bean.filters}" />
    <h:inputHidden id="page" value="#{bean.page}" />
    <h:inputHidden id="npages" value="#{bean.npages}" />
    <h:inputHidden id="scrollPos" value="#{bean.scrollPos}" />
</form>
<script src="js/DataTableFilterStorage.js" />   
<script> $(function(){ loadDatatableState(); }); </script>

The filter values are saved and loaded via javascript. The methods are in the file DataTableFilterStorage.js:

function saveDatatableState(){              
    var filterNormal = $('form .ui-column-filter').serialize();
    var filterCustomText = $('form .ui-column-customfilter .ui-inputfield').serialize()
    if (filterNormal != "" && filterCustomText != "") {
        $(fFilter).val(filterNormal + '&' + filterCustomText);
    } else {
        $(fFilter).val(filterNormal + filterCustomText);
    }
    var page = $('.ui-paginator-page.ui-state-active:first').text();
    if(!page) page = 0;
    var scrollPos = $('body').scrollTop();
    if(!scrollPos) scrollPos = 0;
    $(#page).val(page);
    $(#npages).val($('#yui-pg0-0-rpp').val());
    $(#scrollPos).val(scrollPos);
}

function loadDatatableState(){ 
    var filters = $(#filters).val().split('&');    
    if (filters != ""){
        for(var i = 0; i < filters.length; i++){               
            var f = filters[i].split("=");
            if(f.length != 2 || f[1].length < 1) continue; 
            $('#'+f[0].replace(/%3A/g, '\\:')).val(decodeURIComponent(f[1]).replace('+', ' '));
            //For Dropdown-Menues
            $('#'+f[0].replace(/%3A/g, '\\:') + ' option:selected').val(decodeURIComponent(f[1]).replace('+', ' '));    
        }          
    }      

    var handler = function(e, xhr, settings) {
        if($(#page).val().length > 0 && $(#page).val() != 1){
            var p = $('a.ui-paginator-page[page='+$(#page).val()+']:first');
                if(p.length > 0){
                p.attr('id', 'currentPage');
                var event = document.createEvent("HTMLEvents");
                event.initEvent("click", true, true);
                document.getElementById('currentPage').dispatchEvent(event);
            }
        }
        $(#form).unbind('ajaxComplete', handler);
    };
    $(#form).ajaxComplete(handler);
};

The filter values from a normal text field, a dropdown menu (single select option) and an inputmask are saved and loaded properly, but the filter values form the selectCheckboxMenu aren't.

The reason, why the filters aren't saved properly is the line $(#filter).val($('form .ui-column-filter').serialize());. It saves only filters with the type "ui-column-filter". The filters in from the selectCheckboxMenu are of the type ui-column-customfilter. I tried to select the values by changing the line into $(#filter).val($('form .ui-column-customfilter').serialize()); but it didn't work.

The solution has to work under IE 11. I'm using Primefaces 5.2 and JSF 2.0.


Solution

  • You can use the new multiViewState feature implemented since Primefaces 6.1 to persist dataTable state.