Search code examples
jsfprimefacesdatatableradio-buttonjavabeans

Render different columns in Primefaces datatable


I have a datatable on a page with columns Unit/Set, Vehicle, Next Maintenance, Day 1,...,Day 7. I have two radio buttons also to change the sorting of the data, when I change to the other radio button which sorts by Date instead of Unit/Set the columns should change to Date, A Exams, B Exams, C Exams,...

I assume I need to create two datatables and then use the rendered attribute to decide which table is shown depending on which sort is selected.

<p:dataTable id="dataTableEnquiryNextDue" styleClass="editable-datatable"
                rows="20"
                scrollable="true"
                frozenColumns="2"
                rendered=>                                          
                <p:column headerText="Unit/Set" />
                <p:column headerText="Vehicle" />
                <p:column headerText="Next Maintenance" />
                <p:column headerText="Day 1" />
                <p:column headerText="Day 2" />
                <p:column headerText="Day 3" />
                <p:column headerText="Day 4" />
                <p:column headerText="Day 5" />
                <p:column headerText="Day 6" />
                <p:column headerText="Day 7" />|
            </p:dataTable>

This is my code for the datatable, except I have left the rendered blank at the minute, I believe I'll have to make some kind of bean, I think it will get the value of the radio buttons then I will have something like

rendered="#{Bean.searchSort == Unit}

or

rendered="#{Bean.searchSort == Date}

I have created a bean with the following code

@ManagedBean

@ViewScoped public class DepotWorkloadBean implements Serializable {

public enum Sort    {
    UNIT, DATE
}

private Sort sortMode = Sort.UNIT;

public Sort getSortMode() {
    return sortMode;
}

public void enterUnitSort() {
    sortMode = Sort.UNIT;       
}

public void enterDateSort() {
    sortMode = Sort.DATE;
}

}

And in my table added the line

rendered="#{depotWorkloadBean.sortMode == 'UNIT'}"

I have also created my other table the same way but with

rendered="#{depotWorkloadBean.sortMode == 'DATE'}"

and different columns.

For my radio buttons I have written

            <p:radioButton id="UnitSetNumber" for="customRadio3" itemIndex="0"  
        onchange="#{depotWorkloadBean.enterUnitSort}" update="dataTableDaySortUnit dataTableDaySortDate"/>

            <p:radioButton id="DateDue" for="customRadio3" itemIndex="1"
        onchange="#{depotWorkloadBean.enterDateSort}" update="dataTableDaySortUnit dataTableDaySortDate"/>

At the moment I am getting an error saying

The class 'DepotWorkloadBean' does not have the property 'enterUnitSort'.

This is quite confusing as it clearly does and as far as I can tell I have spelt everything correctly. I'm still not sure if my approach is actually correct though, so again any advice will be appreciated.

Here is my selectOneRadio

                <p:selectOneRadio id="customRadio3" layout="custom">
                <f:selectItem itemLabel="UnitSetNumber" itemValue="1" binding="{depotWorkloadBean.enterUnitSort}"
                update=":mainForm"/>
                <!-- <f:ajax listener="#{depotWorkloadBean.enterUnitSort}" render="@all"/> -->
                <f:selectItem itemLabel="DateDue" itemValue="2" binding="{depotWorkloadBean.enterDateSort}"
                update=":mainForm"/>
                <!-- <f:ajax listener="#{depotWorkloadBean.enterDateSort}" render="@all"/> -->
                <f:selectItem itemLabel="DueInValue" itemValue="3" />
            </p:selectOneRadio>

EDIT: Here is my updated selectOneRadio

<p:selectOneRadio id="customRadio3" layout="custom"
            value="#{depotWorkloadBean.sortMode}"
            update=":mainForm">
                <f:selectItem itemLabel="UNIT.name" itemValue="UNIT" value="#{depotWorkloadBean.sortMode}"
                var="UNIT"/>
                <!-- <f:ajax listener="#{depotWorkloadBean.enterUnitSort}" render="@all"/> -->
                <f:selectItem itemLabel="DATE.name" itemValue="DATE" value="#{depotWorkloadBean.sortMode}"
                var="DATE"/>
                <!-- <f:ajax listener="#{depotWorkloadBean.enterDateSort}" render="@all"/> -->
                <f:selectItem itemLabel="DueInValue" itemValue="3" />
            </p:selectOneRadio>

And here is my updated bean

@ManagedBean
@ViewScoped
public class DepotWorkloadBean implements Serializable {



   public enum Sort {
        UNIT, DATE
    }

    private Sort sortMode = Sort.UNIT;

    public Sort getSortMode() {
        return sortMode;
    }

    public Sort[] getSortValues() {
        return Sort.values();
    }

    public void setSortMode(Sort sortMode) {
        this.sortMode = sortMode;
    }
}

EDIT: After a bit of thinking I have taken a new approach, so now my radio button group is like so:

    <!-- <f:facet name="actions"> -->
        <p:selectOneRadio id="customRadio3" layout="custom"
        partialSubmit="true"
        value="#{depotWorkloadBean.selectSort}">
            <p:ajax update="mainForm" listener="#{depotWorkloadBean.updateSortMode}"/>
            <f:selectItem itemLabel="UnitSet" itemValue="UnitSet"/>        
            <f:selectItem itemLabel="DateDue" itemValue="DateDue"/>            
            <f:selectItem itemLabel="DueInValue" itemValue="DueInValue"/>                     
        </p:selectOneRadio>
    <!-- </f:facet> -->

I have commented out the facet tag as it causes the error "javax.servlet.ServletException" and I have no idea why.

My tables are as they were before except the rendered line is now

rendered="#{depotWorkloadBean.sortMode == 'UnitSet'}">

and similar for 'DateDue'. And my bean is as follows:

@ManagedBean
@ViewScoped
public class DepotWorkloadBean implements Serializable {

private static final Log log = LogFactory.getLog(DepotWorkloadBean.class);

/*public enum Sort {
    UNIT, DATE
}

private Sort sortMode = Sort.UNIT;*/

private String sortMode = "UnitSet";
private String selectSort = "UnitSet";

public void updateSortMode () {
    log.info("In updateSortMode " + " State [" + selectSort + "]");
    sortMode = selectSort;
}

public String getSortMode() {
    return sortMode;
}

public void setSortMode(String sortMode) {
    this.sortMode = sortMode;
}

public String getSelectSort() {
    return selectSort;
}

public void setSelectSort(String selectSort) {
    log.info("Setting selectSort to [" + selectSort + "]");
    this.selectSort = selectSort;
    sortMode = selectSort;
}

I have only just found out about the log and it seems very useful. When my page builds and I click between the radio buttons my log records 'In updateSortMode State []' "Setting selectSort to State []" so there is clearly something going wrong in the method. The other thing I should mention is my radio buttons are actually displayed further down in the same panelGrid, like so..

        <p:row>
    <p:column>
        <p:radioButton id="UnitSetNumber" for="customRadio3" itemIndex="0"/>
    </p:column>    
    <p:column>
        <h:outputLabel for="UnitSetNumber" value="Unit/set number" />
    </p:column>        
    </p:row>
    <p:row>
    <p:column>
        <p:radioButton id="DateDue" for="customRadio3" itemIndex="1"/>
    </p:column>    
    <p:column>
        <h:outputLabel for="DateDue" value="Date due" />
    </p:column>        
    </p:row>
    <p:row>
    <p:column>
        <p:radioButton id="DueInValue" for="customRadio3" itemIndex="2" />
    </p:column>    
    <p:column>
        <h:outputLabel for="DueInValue" value="Due in value" />
    </p:column>        
    </p:row>   

Not sure if that would affect the ajax listener?

Thanks


Solution

  • You don't need an onchange listener, the update= attribute will do the job.

    Use a <p:selectOneRadio> with a nested <f:selectitems> that will set the sortMode value of your bean (you might need a converter). Then ensure the parent component of both tables is updated upon selection. This will re-evaluate the rendered= attributes of your tables with the newly set sortMode valule.

    Example: The view:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
          xmlns:h="http://java.sun.com/jsf/html"
          xmlns:p="http://primefaces.org/ui"
          xmlns:f="http://java.sun.com/jsf/core">
        <h:head>
            <title>TEST</title>
        </h:head>
        <h:body>
            <h:form>
                <p:selectOneRadio id="radiogroup"
                                  value="#{testController.selectedValue}">
                    <f:ajax render=":content"/>
                    <f:selectItems value="#{testController.valuesTypes}"
                                   var="val"
                                   itemLabel="#{val.name()}"
                                   itemValue="#{val}"/>
                </p:selectOneRadio>
            </h:form>
            <h:form id="content">
                <p:outputPanel rendered="#{testController.selectedValue eq 'VALUEA'}">
                    Value A panel
                </p:outputPanel>
                <p:outputPanel rendered="#{testController.selectedValue eq 'VALUEB'}">
                    Value B panel
                </p:outputPanel>
                <p:outputPanel rendered="#{testController.selectedValue eq 'VALUEC'}">
                    Value C panel
                </p:outputPanel>
            </h:form>
        </h:body>
    </html>
    

    And the bean:

    import javax.annotation.PostConstruct;
    import javax.faces.bean.ManagedBean;
    import javax.faces.bean.ViewScoped;
    
    @ManagedBean
    @ViewScoped
    public class TestController {
    
        public enum ValueTypes {
    
            VALUEA,
            VALUEB,
            VALUEC
        }
    
        private ValueTypes selectedValue;
    
        public ValueTypes getSelectedValue() {
            return selectedValue;
        }
    
        public void setSelectedValue(ValueTypes selectedValue) {
            this.selectedValue = selectedValue;
        }
    
        @PostConstruct
        public void init() {
            selectedValue = ValueTypes.VALUEA;
        }
    
        public ValueTypes[] getValuesTypes() {
            return ValueTypes.values();
        }
    }