Problem with multiple sorting in DataTable

UI Components for JSF
ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

13 Oct 2021, 16:29

Hi,

I am having a problem with DataTables. I think there's something wrong globally with the datatable, but I can see the problem for sure when trying to sort the data (filtering also does strange things, but I've removed the filters for now, I think all the problems come from one mistake I've made and I want to fix that first before adding more functionalities).

PrimeFaces version: 7.0
Mojarra JSF 2.2.6
SEAM 2.3.1.Final


I am using (and must use) Seam and its annotations, so the examples in the PF demo page don't work directly in my environment.

XHTML:

Code: Select all

<div xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:c="http://java.sun.com/jstl/core"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:p="http://primefaces.org/ui"
    class="mainNoTabs">

    
    <h3>Workflow Forms</h3>
    
    <script type="text/javascript">
    PrimeFaces.settings.locale = 'en_US';
    </script>

    <h:panelGroup id="datatablePanel" layout="block">
    
        <h:form id="dtForm">
            
            <p:dataTable id="datatable_proba_widget" widgetVar="datatbl_proba_widget" value="#{workflowQuestionsTableBean.data}"
                binding="#{workflowQuestionsTableBean.dataTable}"
                var="rowData"
                rowIndexVar="rowIndex"
                rowKey="#{rowData.id}"
                resizableColumns="true" liveResize="true"
                tableStyleClass="datatable bigFont"
                tableStyle="table-layout: auto;"
                emptyMessage="No Records Found"
                sortMode="multiple"
                >
                
                <f:facet name="header" style="overflow: hidden;">
                    
                    <span class="tableHeaderTitle">Workflow Forms</span>
                    <span class="tableHeaderButtons">
                        
                        <!-- Reload -->
                        <h:commandButton
                            image="/icons/refresh.png"
                            title="Reload"
                            styleClass="button tipsyShow tipsyGravityN"
                            style="width: 48px; height: 24px; padding: 4px 16px;">
                            
                            <p:ajax
                                immediate="true"
                                listener="#{workflowQuestionsTableBean.reload}"
                                process="@this"
                                partialSubmit="true"
                                update="datatable_proba_widget"
                            />
                            
                        </h:commandButton>
                        
                    </span>
                    
                </f:facet>
                
                
                <!-- COLUMN 1 workflowId -->
                <p:column styleClass="datatableColumn" visible="true" sortBy="#{rowData.workflowId}" sortOrder="ascending" sortPriority="1">
                    
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Workflow" style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_workflow">
                        #{rowData.workflowId}
                    </h:panelGroup>
                </p:column>
                
                
                <!-- COLUMN 2 nodeId -->
                <p:column styleClass="datatableColumn" visible="true" sortBy="#{rowData.nodeId}" sortOrder="ascending" sortPriority="2">
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Node"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                        
                    <h:panelGroup id="tableWidget_node">
                        #{rowData.nodeId}
                    </h:panelGroup>
                </p:column>
                
                
                <!-- COLUMN 3 questionId -->
                <p:column styleClass="datatableColumn" visible="true">
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Question"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_question">
                        #{rowData.questionId}
                    </h:panelGroup>
                </p:column>
                
                <!-- COLUMN 4 type -->
                <p:column styleClass="datatableColumn" visible="true">
                    
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Type"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_type">
                        #{rowData.type}
                    </h:panelGroup>
                </p:column>
                
                <!-- COLUMN 5 required -->
                <p:column styleClass="datatableColumn" visible="true">
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Required"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_required">
                        #{rowData.required}
                    </h:panelGroup>
                </p:column>
                
                <!-- COLUMN 6 order -->
                <p:column styleClass="datatableColumn" visible="true" sortBy="#{rowData.order}" sortOrder="ascending" sortPriority="3">
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Order"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_order">
                        #{rowData.order}
                    </h:panelGroup>
                </p:column>
                
                <!-- COLUMN 7 obsolete -->
                <p:column styleClass="datatableColumn" visible="true">
                    
                    <f:facet name="header">
                        <span>
                            <h:outputText value="Obsolete"
                                style="white-space:pre-line;" />
                        </span>
                    </f:facet>
                    
                    <h:panelGroup id="tableWidget_obsolete">
                        #{rowData.obsolete}
                    </h:panelGroup>
                </p:column>
                
            </p:dataTable>
        
        </h:form>
        
        
    </h:panelGroup>
    
</div>
Bean:

Code: Select all

package org.example.package;

import static org.jboss.seam.ScopeType.CONVERSATION;
import static org.jboss.seam.annotations.Install.APPLICATION;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.model.SortMeta;
import org.primefaces.model.SortOrder;

@Name("workflowQuestionsTableBean")
@Scope(CONVERSATION)
@Install(precedence = APPLICATION)
public class WorkflowQuestionsTableBean implements Serializable {

    private static final long serialVersionUID = 1L;

    private List<WorkflowQuestionRowData> data;

    protected DataTable dataTable;

    public WorkflowQuestionsTableBean() {
        data = new ArrayList<WorkflowQuestionRowData>();
    }

    @Create
    public void init() {
        createData();
    }

    public List<WorkflowQuestionRowData> getData() {
        return data;
    }

    public void setData(List<WorkflowQuestionRowData> data) {
        this.data = data;
    }

    public DataTable getDataTable() {
        return dataTable;
    }

    public void setDataTable(DataTable dataTable) {
        this.dataTable = dataTable;
    }

    public void reload() {
        createData();
    }

    public void orderTable() {

        DataTable dt = getDataTable();
        
        // when it enters for the first time, datatable is null
        if (dt != null) {
            List<SortMeta> multiSortMeta = new ArrayList<>();

            SortMeta sortMeta1 = new SortMeta();
            sortMeta1.setSortOrder(SortOrder.ASCENDING);
            sortMeta1.setSortBy(dt.getColumns().get(0));
            multiSortMeta.add(sortMeta1);

            SortMeta sortMeta2 = new SortMeta();
            sortMeta2.setSortOrder(SortOrder.ASCENDING);
            sortMeta2.setSortBy(dt.getColumns().get(1));
            multiSortMeta.add(sortMeta2);

            SortMeta sortMeta3 = new SortMeta();
            sortMeta3.setSortOrder(SortOrder.ASCENDING);
            sortMeta3.setSortBy(dt.getColumns().get(5));
            multiSortMeta.add(sortMeta3);

            dt.setMultiSortMeta(multiSortMeta);
        }
    }

    public void createData() {
        try {

            setData(generateData());
            orderTable();

        } catch (Exception e) {

            // Write exception in logs
        }
    }

    private List<WorkflowQuestionRowData> generateData() {

        List<WorkflowQuestionRowData> data = new ArrayList<WorkflowQuestionRowData>();

        // ONE
        String rowId = "1";
        String workflowId = "Worfklow1";
        String nodeId = "Node1";
        String questionId = "Question1";
        String type = "TypeA";
        boolean required = false;
        int order = 3;
        boolean obsolete = false;

        data.add(new WorkflowQuestionRowData(rowId, workflowId, nodeId,
                questionId, type, required, order, obsolete));

        // TWO
        rowId = "2";
        workflowId = "Worfklow1";
        nodeId = "Node2";
        questionId = "Question2";
        type = "TypeA";
        required = false;
        order = 3;
        obsolete = false;

        data.add(new WorkflowQuestionRowData(rowId, workflowId, nodeId,
                questionId, type, required, order, obsolete));

        // THREE
        rowId = "3";
        workflowId = "Worfklow1";
        nodeId = "Node1";
        questionId = "Question3";
        type = "TypeA";
        required = false;
        order = 1;
        obsolete = false;

        data.add(new WorkflowQuestionRowData(rowId, workflowId, nodeId,
                questionId, type, required, order, obsolete));

        // FOUR
        rowId = "4";
        workflowId = "Worfklow1";
        nodeId = "Node2";
        questionId = "Question4";
        type = "TypeA";
        required = false;
        order = 2;
        obsolete = false;

        data.add(new WorkflowQuestionRowData(rowId, workflowId, nodeId,
                questionId, type, required, order, obsolete));

        // FIVE
        rowId = "5";
        workflowId = "Worfklow1";
        nodeId = "Node2";
        questionId = "Question5";
        type = "TypeA";
        required = false;
        order = 1;
        obsolete = false;

        data.add(new WorkflowQuestionRowData(rowId, workflowId, nodeId,
                questionId, type, required, order, obsolete));

        return data;
    }

}

And WorkflowQuestionRowData is this:

Code: Select all

/*
 * (C) Copyright 2015 Aritu S Coop (http://aritu.com/).
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Lesser General Public License
 * (LGPL) version 2.1 which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/lgpl.html
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 */
package com.aritu.eloraplm.workflows.forms.datatable;

import java.io.Serializable;

/**
 *
 * @author aritu
 *
 */
public class WorkflowQuestionRowData implements Serializable {

    private static final long serialVersionUID = 1L;

    private String id;

    private String workflowId;

    private String nodeId;

    private String questionId;

    private String type;

    private boolean required;

    private int order;

    private boolean obsolete;

    public WorkflowQuestionRowData(String rowId, String workflowId,
            String nodeId, String questionId, String type, boolean required,
            int order, boolean obsolete) {

        id = rowId;
        this.workflowId = workflowId;
        this.nodeId = nodeId;
        this.questionId = questionId;
        this.type = type;
        this.required = required;
        this.order = order;
        this.obsolete = obsolete;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getWorkflowId() {
        return workflowId;
    }

    public void setWorkflowId(String workflowId) {
        this.workflowId = workflowId;
    }

    public String getNodeId() {
        return nodeId;
    }

    public void setNodeId(String nodeId) {
        this.nodeId = nodeId;
    }

    public String getQuestionId() {
        return questionId;
    }

    public void setQuestionId(String questionId) {
        this.questionId = questionId;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public boolean getRequired() {
        return required;
    }

    public void setRequired(boolean required) {
        this.required = required;
    }

    public int getOrder() {
        return order;
    }

    public void setOrder(int order) {
        this.order = order;
    }

    public boolean getObsolete() {
        return obsolete;
    }

    public void setObsolete(boolean obsolete) {
        this.obsolete = obsolete;
    }

}
I have configured the multiple sorting in the xhtml as you can see, but it doesn't work. And this is what I see (columns are sortable, but sorting isn't activated):
Image

So, I have decided to sort it from the bean, with the method orderTable(). Now, it doesn't work when the page loads, but if I press the reload button (reload() method), it works. I don't really know what is happening. I don't know why it doesn't sort with the configuration in the template, and I don't know why when I load the page for the first time, the dataTable binding is still null (so I can't set the MultiSortMeta).

As I've said before, I use Seam, and the @Create annotation. I don't know if that can be a problem.

Please let me know if you need more information.


Thank you very much in advance ;)

ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

13 Oct 2021, 16:30

I don't know why the image isn't displayed. You can see it here: https://ibb.co/BzQL3zB

NOTiFY
Posts: 393
Joined: 25 May 2016, 22:57

13 Oct 2021, 17:26

Seem to remember a number of years ago I had to switch :

JBoss Seam 2.3.1.Final (2013) to JBoss Weld CDI (https://weld.cdi-spec.org/)

I had issues with an earlier version of PrimeFaces (5, 6 & early 7) using DataTables (I use it a lot)
PF 13.0.0--Jakarta. Jakarta Faces 4.0.1/Kotlin Multiplatform 1.9.10
Mojarra 4.0.2, OmniFaces 4.2
WildFly 29.0.1.Final 'preview' Jakarta EE 10.0.0
JDK 20.0.2, Kotlin 1.9.10, Gradle 8.3 Groovy DSL, MongoDB 7.0.0
IntelliJ IDEA 2023.2.1, macOS Ventura 13.5.1

ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

13 Oct 2021, 18:06

Hi NOTiFY,
I hope that is not causing the problem, because I can't move from Seam. The datatable is in a plugin of an existing software, and we are stuck with the libraries/frameworks that this software uses.

Thanks for the reply ;)

NOTiFY
Posts: 393
Joined: 25 May 2016, 22:57

13 Oct 2021, 18:36

What do mean "datatable is in a plugin of an existing software"

Code: Select all

public class WorkflowQuestionRowData implements Serializable {
Looks like it's just an 'Entity' object. PF DataTable will get the data from the Entity.

Has no:

Code: Select all

@Embeddable
PF 13.0.0--Jakarta. Jakarta Faces 4.0.1/Kotlin Multiplatform 1.9.10
Mojarra 4.0.2, OmniFaces 4.2
WildFly 29.0.1.Final 'preview' Jakarta EE 10.0.0
JDK 20.0.2, Kotlin 1.9.10, Gradle 8.3 Groovy DSL, MongoDB 7.0.0
IntelliJ IDEA 2023.2.1, macOS Ventura 13.5.1

ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

14 Oct 2021, 11:07

I'm sorry I didn't explain it well. We are developing an extension for a Digital Assets Management (DAM) system, so I mean that we can't move from Seam 2.3.1.Final because it is used by the DAM system.

WorkflowQuestionRowData is not an Entity.


The datatable should get ordered with the attributes I've set to the columns (sortBy, sortOrder, sortPriority), right?

And I guess that when @Create method is called, dataTable shouldn't be null, also, or am I wrong?

Thank you!

NOTiFY
Posts: 393
Joined: 25 May 2016, 22:57

14 Oct 2021, 12:36

In:

Code: Select all

public class WorkflowQuestionsTableBean implements Serializable {
You don't seem to have @Produces to send back to the client.

Like ...

Code: Select all

@Produces
public List<Motorcycle> getAllNOTiFYs() {
    if (motorcycleList == null) {
        motorcycleList = motorcyclesEJB.getAllMotorcycles();
    }
    return motorcycleList;
}
To PF:

Code: Select all

 <p:dataTable id="dataTableMotorcycles" var="motorcycle"
                     value="#{nOTiFYMotorcycleController.allNOTiFYs}"
PF 13.0.0--Jakarta. Jakarta Faces 4.0.1/Kotlin Multiplatform 1.9.10
Mojarra 4.0.2, OmniFaces 4.2
WildFly 29.0.1.Final 'preview' Jakarta EE 10.0.0
JDK 20.0.2, Kotlin 1.9.10, Gradle 8.3 Groovy DSL, MongoDB 7.0.0
IntelliJ IDEA 2023.2.1, macOS Ventura 13.5.1

ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

14 Oct 2021, 18:05

I've added @Produces to the method getData():

Code: Select all

@Produces
public List<WorkflowQuestionRowData> getData() {
        return data;
}
but nothing changed...

NOTiFY
Posts: 393
Joined: 25 May 2016, 22:57

14 Oct 2021, 18:25

Can't you print the output from:

Code: Select all

List <WorkflowQuestionRowData> data
on your EE (WildFly, Jetty. Tomcat etc.) 'Terminal'.
PF 13.0.0--Jakarta. Jakarta Faces 4.0.1/Kotlin Multiplatform 1.9.10
Mojarra 4.0.2, OmniFaces 4.2
WildFly 29.0.1.Final 'preview' Jakarta EE 10.0.0
JDK 20.0.2, Kotlin 1.9.10, Gradle 8.3 Groovy DSL, MongoDB 7.0.0
IntelliJ IDEA 2023.2.1, macOS Ventura 13.5.1

ioihanguren
Posts: 15
Joined: 11 Feb 2016, 00:08

15 Oct 2021, 10:40

This is what I get:

Code: Select all

[com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@47395d21,
com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@2ce377ff,
com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@73e96c2b,
com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@57f67b44,
com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@5a2be4ce]
But then I've overridden WorkflowQuestionRowData.toString() method to show more information:

Code: Select all

    @Override
    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode())
                + "\n" + "id= " + id + "\n" + "workflowId= " + workflowId + "\n"
                + "nodeId= " + nodeId + "\n" + "questionId= " + questionId
                + "\n" + "type= " + type + "\n" + "required= " + required + "\n"
                + "order= " + order + "\n" + "obsolete= " + obsolete + "\n";
    }
Now I get:

Code: Select all

[com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@2a432d70
id= 1
workflowId= Worfklow1
nodeId= Node1
questionId= Question1
type= TypeA
required= false
order= 3
obsolete= false
, com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@714f80e3
id= 2
workflowId= Worfklow1
nodeId= Node2
questionId= Question2
type= TypeA
required= false
order= 3
obsolete= false
, com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@6e3a2ee5
id= 3
workflowId= Worfklow1
nodeId= Node1
questionId= Question3
type= TypeA
required= false
order= 1
obsolete= false
, com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@6b6171d4
id= 4
workflowId= Worfklow1
nodeId= Node2
questionId= Question4
type= TypeA
required= false
order= 2
obsolete= false
, com.aritu.eloraplm.workflows.forms.datatable.WorkflowQuestionRowData@58faf965
id= 5
workflowId= Worfklow1
nodeId= Node2
questionId= Question5
type= TypeA
required= false
order= 1
obsolete= false
]

Post Reply

Return to “PrimeFaces”

  • Information
  • Who is online

    Users browsing this forum: No registered users and 22 guests