Sorting is not working in datatable in PrimeFaces?

2019-01-23 14:29发布

问题:

Sorting is not working in datatable in PrimeFaces. Please suggest.

See below my .xhtml file

<h:form>

  <p:dataTable style="width: 60%" id="dt1" value="#{bean.list}" var="entry" first="0" paginator="true" rows="10" paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="5,10,15" emptyMessage="No cars found with given criteria" >

    <f:facet name="header">
      <h2>Cars View</h2>
    </f:facet>

    <p:column sortBy="#{entry.carno}" filterBy="#{entry.carno}">
      <f:facet name="header">
        <h:outputText value="Car Number" />
      </f:facet>
      <h:outputText value="#{entry.carno}"></h:outputText>
    </p:column>

    <p:column sortBy="#{entry.carsettings['car-model']}" filterBy="#{entry.carsettings['car-model']}">
      <f:facet name="header">
        <h:outputText value="Car Model"/>
      </f:facet>
      <h:outputText value="#{entry.carsettings['car-model']}"></h:outputText>
    </p:column>

    <p:column sortBy="#{entry.carsettings.year}" filterBy="#{entry.carsettings.year}">
      <f:facet name="header">
        <h:outputText value="Car Year"/>
      </f:facet>
      <h:outputText value="#{entry.carsettings.year}"></h:outputText>
    </p:column>

    <p:column sortBy="#{entry.carsettings.color}" filterBy="#{entry.carsettings.color}">
      <f:facet name="header">
        <h:outputText value="Car Color"/>
      </f:facet>
      <h:outputText value="#{entry.carsettings.color}"></h:outputText>
    </p:column>
  </p:dataTable>
</h:form>

@Sean

Look below code

List of Cars

    <ui:composition template="/template.xhtml">
        <ui:define name="content">
            <f:view>
                <f:event type="preRenderView" listener="#{MyBackingBean.load}"></f:event>
                <center>
                    <h1>Car View</h1>
                    <h:outputText value="No data found" style="font-size: 15px;font-family: Arial, Verdana,Helvetica, sans-serif" rendered="#{MyBackingBean.noDataExist}"></h:outputText>
                    <h:form id="dataform1">
                        <p:dataTable var="item" value="#{MyBackingBean.dataList}" dynamic="true" paginator="true" rows="2" id="table"  style="width:60%"
                                     rendered="#{!MyBackingBean.noDataExist}" >
                            <p:column sortBy="#{item.id}" filterBy="#{item.id}">
                                <f:facet name="header">
                                    <h:outputText value="ID" />
                                </f:facet>
                                <h:outputText value="#{item.id}" />
                            </p:column>
                            <p:column sortBy="#{item.carsettings['car-color']}" filterBy="#{item.carsettings['car-color']}">
                                <f:facet name="header">
                                    <h:outputText value="Color" />
                                </f:facet>
                                <h:outputLink target="_blank" value="http://#{item.carsettings['car-color']}">
                                    <h:outputText value="#{item.carsettings['car-color']}" />
                                </h:outputLink>
                            </p:column>
                            <p:column sortBy="#{item.carsettings.model}" filterBy="#{item.carsettings.model}">
                                <f:facet name="header">
                                    <h:outputText value="Model" />
                                </f:facet>
                                <h:outputText value="#{item.carsettings.model}" />
                            </p:column>
                            <p:column sortBy="#{item.carsettings.manufacturer}" filterBy="#{item.carsettings.manufacturer}">
                                <f:facet name="header">
                                    <h:outputText value="Manufacturer" />
                                </f:facet>
                                <h:outputText value="#{item.carsettings.manufacturer}" />
                            </p:column>
                        </p:dataTable>
                    </h:form>
                </center>
            </f:view>
        </ui:define>
    </ui:composition>
</h:body>

Sorting is not working in the above code

Please help

回答1:

The primefaces backing bean (ViewScoped!) must hold it's own List of rows. So, e.g., if you query the database every time you request the p:dataTable:value, sorting will not work.

Solution: Collect the List from the Database and keep it in a local List variable in the backing bean.

public List<Row> getDataTable() {
    if (tableDataList == null)
        tableDataList = loadListOnce();
    return tableDataList;
}


回答2:

The Problem is:

<f:event type="preRenderView" listener="#{MyBackingBean.load}"></f:event>

Sorting is done by the <p:dataTable/> at PhaseId.APPLY_REQUEST_VALUES on the list, with the <f:event type"preRenderView"/> you reload the list at PhaseId.RENDER_RESPONSE and so you lost the sorting.

Solution: use <f:event type="postAddToView"/>

<f:event type="postAddToView" listener="#{MyBackingBean.load}" />

This will reload the list at PhaseId.RESTORE_VIEW before sorting is done by <p:dataTable/>.

Tested with PrimeFaces Version 3.1.1 and Mojarra 2.1.8



回答3:

If you populate your table in the getter sorting wont work (as described above). You should put in your getter like:

public List<Row> getTableData() {
    if (tableDataList == null)
        tableDataList = dao.getTableData();
    return tableDataList;
}

You can then reset(refresh) your "cash" by punting tableDataList = null; if you wont your datatabele refreshed.



回答4:

My Service had:

public List<PlayerEntity> getAllPlayers() {
    return playerDao.readAll();
}

but that was wrong, because when I was calling getAllPlayers() from table

<p:dataTable id="data" value="#{myBean.allPlayers}"/>

I got from DAO refreshed data but still unordered. Instead of that I've created List field and method to update the List

private List<PlayerEntity> allPlayers = new ArrayList<PlayerEntity>();  

public void updateAllPlayers(){
    this.allPlayers = playerDao.readAll();
}

which method I'm running on bean initialization

public void setPlayerDao(PlayerDao playerDao) {
    this.playerDao = playerDao;
    updateAllPlayers();
}

and after Add, Delete or Modiffy the List

public boolean createPlayer(PlayerEntity playerEntity) {
    (...)
    updateAllPlayers();
    return true;
}

Now my Service has

public List<PlayerEntity> getAllPlayers() {
    return this.allPlayers;
}

and that solved my problem with sorting data in Primefaces table.



回答5:

I had a problem sorting when my backing bean was sessionScoped. Not sure what your exact problem is, but if you hit the sort button and nothing happens, try changing your scope to @ViewScoped.



回答6:

have you tried @SessionScoped? it works fine to me, hope this help.



回答7:

I don't know if it's your case. There's a primefaces issue. A bug on sort of datatable. Take a look here: https://code.google.com/archive/p/primefaces/issues/2476

There are some workarounds:

  1. you can use a lazyDataModel for your datatable, it works.

  2. you can force the sort order.

In your datatable catch the sort event

<p:dataTable style="width: 60%" id="dt1" value="#{bean.list}" var="entry" first="0" paginator="true" rows="10" paginatorTemplate="{CurrentPageReport}  {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}" rowsPerPageTemplate="5,10,15" emptyMessage="No cars found with given criteria" >
<p:ajax event="sort" listener="#bean.sortListener}" />

In your managed bean you set a order by string to add to your query

private String orderBy = "";

public void sortListener(SortEvent event) {
    String orderColumn = event.getSortColumn().getValueExpression("sortBy").getExpressionString();

    //you will get the content of the attribute SortBy of the column you clicked on, like #{entry.carno}
    orderColumn = orderColumn.replace("#{entry.", "");
    orderColumn = orderColumn.replace("}", "");
    orderBy = " order by " + orderColumn + (event.isAscending()? " asc " : " desc ");
}

public List<Car> getList(){
    String query = "[...your query...]" + orderBy;
    ...[execute your query and get your ordered list]
}