1
votes

I have a datatable with lazy data model and pagination. I want to disable default sorting when I click on "search" button and enable it again when I click on "display" button. So didn't put "sortBy" in my xhtml file and instead, I set it dynamically in my backing bean.

Everything works properly until I click on the header to flip sort order between descending and ascending. It means the "search" button disables the sorting and "display" button enables it correctly if I don't click on the header. But when I click on the header and then click the "search" button, in load funciton of LazyDataModel, value of the argument sortField is "date" and the datatable will be sorted by date though the "date" column is not colored apparently!!

This is my datatable:

<h:form id="contents-form">
...
    <p:dataTable id="tbl" widgetVar="tbl" var="msg" value="#{homeController.messagesModel}" lazy="true"
                 currentPageReportTemplate="سطر {startRecord}-{endRecord} از {totalRecords}"
                 paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
                 paginator="true" rows="10" rowsPerPageTemplate="5,10,15"
                 emptyMessage="هیچ پیامکی وجود ندارد."
                 selection="#{homeController.selectedMessages}" rowSelectMode="checkbox"
                 rowKey="#{msg.id}" filteredValue="#{homeController.filteredMessage}"
                 editable="true" editMode="cell"
                 style="width:100%" dir="rtl">

        <f:facet name="header">
            <p:commandButton value="خروجی" action="#{homeController.prepareExport}" icon="fa fa-save"
                             update="export-dlg-box" oncomplete="PF('exportDlgBox').show()"/>
            <p:commandButton value="واژگان" action="#{homeController.showListTermsChart}"
                             icon="fa fa-bar-chart" update="contents-form chart-form msgs"
                             oncomplete="PF('chartDlgBox').show()"/>
        </f:facet>

        <p:ajax event="cellEdit" listener="#{homeController.onCellEdit}" oncomplete="updateDescFilter()"/>

        <p:column selectionMode="multiple" style="width:16px;text-align:center"/>

        <p:column headerText="فرستنده" style="width:100px" filterBy="#{msg.sender.number}"
                  sortBy="#{msg.sender.number}">
            <p:commandLink action="#{homeController.setPhoneNumToShow(msg.sender)}" update="phone-form"
                           oncomplete="PF('phoneDlgBox').show()" styleClass="simple-command-link">
                <h:outputText value="#{msg.sender.number}"/>
            </p:commandLink>
        </p:column>

        <p:column headerText="گیرنده" style="width:100px" filterBy="#{msg.receiver.number}"
                  sortBy="#{msg.receiver.number}">
            <p:commandLink action="#{homeController.setPhoneNumToShow(msg.receiver)}" update="phone-form"
                           oncomplete="PF('phoneDlgBox').show()" styleClass="simple-command-link">
                <h:outputText value="#{msg.receiver.number}"/>
            </p:commandLink>
        </p:column>

        <p:column headerText="متن" sortBy="#{msg.text}">
            <h:outputText value="#{msg.getTrimmedText()}"/>
        </p:column>

        <p:column headerText="زمان" style="width:100px" filterBy="#{msg.date}" sortBy="#{msg.date}">
            <f:facet name="filter">
                <p:calendar pattern="yyyy-MM-dd">
                    <p:ajax event="dateSelect" oncomplete="PF('tbl').filter()" update="tbl"/>
                </p:calendar>
            </f:facet>
            <h:outputText value="#{msg.getJalaliDate()}"/>
        </p:column>

        <p:column headerText="منبع" style="width:70px" filterBy="#{msg.source}" sortBy="#{msg.source}">
            <f:facet name="filter">
                <p:selectOneMenu onchange="PF('tbl').filter()" style="width:30px; direction:ltr">
                    <f:selectItem itemLabel="همه" itemValue="#{null}" noSelectionOption="true"/>
                    <f:selectItems value="#{homeController.sources}" var="source"
                                   itemValue="#{source}" itemLabel="#{source}"/>
                </p:selectOneMenu>
            </f:facet>
            <h:outputText value="#{msg.source}"/>
        </p:column>

        <p:column headerText="توضیح" style="width:70px" filterBy="#{msg.description}"
                  sortBy="#{msg.description}">
            <f:facet name="filter">
                <p:selectOneMenu id="desc-filter-select" onchange="PF('tbl').filter()"
                                 style="width:30px; direction:ltr">
                    <f:selectItem itemLabel="همه" itemValue="#{null}" noSelectionOption="true"/>
                    <f:selectItems value="#{homeController.descriptions}" var="desc"
                                   itemValue="#{desc}" itemLabel="#{desc}"/>
                </p:selectOneMenu>
            </f:facet>
            <p:cellEditor>
                <f:facet name="output"><h:outputText value="#{msg.description}"/></f:facet>
                <f:facet name="input"> <p:inputText id="desc-input" value="#{msg.description}"
                                                    style="width:85%"/></f:facet>
            </p:cellEditor>
        </p:column>

        <p:column headerText="جزئیات" style="width:40px">
            <p:commandLink action="#{homeController.setMessageToShow(msg)}" ajax="true"
                           update="img-dlg-box" oncomplete="PF('imgDlgBox').show()">
                <i class="fa fa-blue fa-desktop"/>
            </p:commandLink>
        </p:column>

        <p:column headerText="مشاهده گفتگو" style="width:40px">
            <p:commandLink action="#{homeController.showConversation(msg.sender, msg.receiver)}"
                           ajax="true" update="conv-dlg-box" oncomplete="PF('convDlgBox').show()">
                <i class="fa fa-blue fa-wechat"/>
            </p:commandLink>
        </p:column>
    </p:dataTable>
</h:form>

My "search" button:

<p:commandButton value="جست‌وجو" action="#{homeController.search}" update=":contents-form:tbl msgs"
                                     icon="fa fa-search"/>

My "display" button:

<p:commandButton value="نمایش" icon="fa fa-desktop" action="#{homeController.loadArchive}"
                 update="contents-form msgs"/>

search method in the backing bean:

public void search() {
    if (this.selectedArchive == null) {
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "لطفا یک مجموعه را انتخاب کنید"));
        return;
    }

    if ((this.textQuery != null && !this.textQuery.equals(""))
            || (this.selectedNodes != null && this.selectedNodes.length > 0)) {
        logger.info(String.format("searching '%s' in archive %d ...", this.textQuery, this.selectedArchive.getId()));
        List<String> selectedWords = this.getSelectedWords(this.selectedNodes);
        searchText(this.textQuery, selectedWords);
    } else {
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "برای جست‌وجو هیچ متنی وارد نشده و هیچ واژه‌ای انتخاب نشده است."));
        return;
    }

    extractChoices();

    // Disable default sorting:
    DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(":contents-form:tbl");
    table.setValueExpression("sortBy", null);
    table.setValueExpression("sortOrder", null);
}

And loadArchive method in the backing bean:

public void loadArchive() {
    if (this.selectedArchive == null) {
        FacesContext.getCurrentInstance().addMessage(null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR, "خطا!", "لطفا یک مجموعه را انتخاب کنید"));
        return;
    }
    this.messagesModel = new LazyMessageModel(this.selectedArchive, true, this.messageService);

    extractChoices();

    // Enable default sorting:
    FacesContext context = FacesContext.getCurrentInstance();
    ExpressionFactory ef = context.getApplication().getExpressionFactory();
    DataTable table = (DataTable) context.getViewRoot().findComponent(":contents-form:tbl");
    ValueExpression sortVe = ef.createValueExpression(context.getELContext(), "#{msg.date}", Message.class);
    table.setValueExpression("sortBy", sortVe);
    table.setSortOrder("descending");

    logger.info(String.format("archive %d loaded", (this.selectedArchive.getId())));
}

Spec:

  • Primefaces 6.2
  • JSF 2.2.14
  • Java 1.8
1
Is it really important to have the sort by disabled in the server? Otherwise you can maybe just use CSSKukeltje
@Kukeltje I do not want to disable sorting permanently. I just want to disable default sorting. How can I do it just by CSS? I think using CSS I can just disable the sort button. But I cannot tell the datatable sort the rows by my order instead of any column.Hossein Forghani
Then I totally do not get your issue. You seem to be trying to solve something that creates a problem which in turn you are trying to solve. This sounds like a xyproblem.infoKukeltje
@Kukeltje Thanks for introducing xyproblem! It was interesting! OK! My first problem (x) is: "I want to tell the datatable not to sort the rows by any column when I click the search button. And sort by date when I click the display button." Of course I mean default sort. User can sort by any column by clicking on the headers after showing the table. I would be glad by any front-end or back-end solution which solves my problem!Hossein Forghani
Just tell the messagesModel which button was press and do the sorting based on that.Jasper de Vries

1 Answers

1
votes

I finally found a clean solution! Just I must reset the table in addition to setting sortBy null after clicking "search" button:

public void search() {
    // Do something ...
    DataTable table = (DataTable) FacesContext.getCurrentInstance().getViewRoot().findComponent(":contents-form:tbl");
    table.reset();
    table.setValueExpression("sortBy", null);
}