5
votes

I'm using a PrimeFaces DataTable to display records (randomly generated in a sandbox application). I am using the check box selection version. The basic DataTable works perfectly, including the Delete and Cancel buttons (which functionality only really is available from the confirmation dialog). I am trying to add functionality to the DataTable so that when a check box is selected, other controls on the page are enabled or disabled based on the selection.

In other words, if no rows are selected (no check boxes are checked) certain buttons and/or menu items are disabled or not rendered. Selecting one or more rows by clicking the check box should enable or render the controls. I have tried using the built in JavaScript event handlers, but I cannot make this work.

Right now my page displays a DataTable 5 columns: a check box selection column, First Name, Last Name, Age. I made something like this work in another sandbox of mine using simple boolean check boxes and updating a boolean with the onclick event. Unfortunately, there doesn't seem to be anything similar in this DataTable - or if there is I don't know how to implement it.

My index page:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:ui="http://java.sun.com/jsf/facelets">

    <body>

        <ui:composition template="./newTemplate.xhtml">


            <ui:define name="content">
            <h:form>

                <p:dataTable rowSelectListener="#{tableBean.onRowSelect}" var="data" value="#{tableBean.data}" paginator="true" rows="10"
                     selection="#{tableBean.selectedNames}">

                <f:facet name="header">
                    Customer List
                </f:facet>


                <p:column selectionMode="multiple" />

                <p:column headerText="Cust ID">
                    <h:outputText value="#{data.id}" />
                </p:column>

                <p:column headerText="First Name">
                    <h:outputText value="#{data.firstName}" />
                </p:column>

                <p:column headerText="Last Name">
                    <h:outputText value="#{data.lastName}" />
                </p:column>

                <p:column headerText="Age">
                    <h:outputText value="#{data.age}" />
                </p:column>

                <f:facet name="footer">                        
                    <p:commandButton update="deleteList" value="Delete" oncomplete="deleteDlg.show()" />
                </f:facet>

            </p:dataTable>

            <p:dialog header="Delete Selected Records" modal="true" widgetVar="deleteDlg"
                      >

                <h:outputText value="You are about to permanently delete records." /><br /><br />
                <h:outputText value="Are you sure you want to continue?" /><br /><br/>

                <h:commandButton value="CANCEL" action="#{tableBean.cancelDelete()}" /> <h:commandButton value="Delete" action="#{tableBean.deleteNames()}" />
            </p:dialog>

        </h:form>
            </ui:define>

        </ui:composition>

    </body>
</html>

Code from my backing bean which may be relevant:

    public void deleteNames()
    {
        for(Data person : selectedNames)
        {
            data.remove(person);
        }   
    }

    public void cancelDelete()
    {
        for(Data name : selectedNames)
            selectedNames = null;
    }

    public void onRowSelect(SelectEvent event)
    {
        if(selectedNames == null || selectedNames.length < 1)
            setDisable(true);
        else
            setDisable(false);
    }

public boolean isDisable() {
        if(selectedNames == null || selectedNames.length < 1)
            disable = true;
        else
            disable = false;
        return disable;
    }

    public void setDisable(boolean disable) {
        this.disable = disable;
    }
3
Well, the only work around I've been able to come up with is to abandon the check boxes. PrimeFaces has an "instant selection" option where you click anywhere on the datatable row to select it. Using that option, with selectionMode="multiple", and changing my commandButtons from standard JSF to PrimeFaces commandButtons, I am able to toggle them on and off when rows are selected or unselected. I would still rather use the check boxes for selection, but that doesn't seem possible with a PrimeFaces datatable.Sean

3 Answers

1
votes

There is a workaround indeed, at least work for me.

  • extract the datatable.js from primefacess
  • modify the datatable.js selectRowWithRadio,selectRowWithRadio functions as below
        PrimeFaces.widget.DataTable.prototype.selectRowWithCheckbox = function(element) {
            ...
            ...
            //save state
            this.writeSelections();
    
            // added to add instant row selection 
            this.fireRowSelectEvent(rowId);
            // end
        }
    
  • Append the javascript below to end of your datatable component
    <p:datatable widgetVar="wv1" id='mydatatable' ....>
    ...
    <p:datatable/>
    <script type="text/javascript">
        if(!wv1_main.cfg.onRowSelectUpdate){
            wv1.cfg.onRowSelectUpdate="";
        }else{
            wv1.cfg.onRowSelectUpdate+=" ";
        }
        wv1.cfg.onRowSelectUpdate+="UPDATE_IDS";
    </script>
    
    Replace 'UPDATE_IDS' with your panel ids seperated by space such as "panel1 panel2";
    Replace 'wv1' with the value of data table widgetVar property
  • import the modified js in your jsf page where you want to use instant ajax checkbox/radia selection.
    <h:header/>
    ...
    <script type="text/javascript" src="#{CONTEXT_PATH}/resources/js/datatable.js"/>
    <h:header/>
    

you may highligh selected rows with some more modification

1
votes

Was just searching for solution to the same problem and since JSF 2 / Primefaces are evolving quite fast these days, found more up-to-date solution for Primefaces of version 3.0 or higher.

As per following answer in PrimeFaces forum thread: http://forum.primefaces.org/viewtopic.php?f=3&t=1373&sid=bbfcd6a343edf586f927cd7ecd7d01b9&start=10#p48388

one can add client-side javascript handler to <p:datatable> component by doing following steps:

1.Add primefaces-extension JAR to your webapp's classpath (this library is also available in central Maven repo under the same name). I tried version 0.6.3 which was the latest at the time of writing, and it worked for me

2.Add pe namespace to corresponding xhtml file:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:p="http://primefaces.prime.com.tr/ui"
      xmlns:c="http://java.sun.com/jsp/jstl/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:pe="http://primefaces.org/ui/extensions">

      ...

</html>

3.Add <pe:javascript> as a child element to your <p:datatable> component (can be actually added to any component which implements ClientBehaviorHolder interface) like the following:

<html>
    ...
    <p:dataTable rowSelectListener="#{tableBean.onRowSelect}" var="data" value="#{tableBean.data}" paginator="true" rows="10" selection="#{tableBean.selectedNames}">
        <pe:javascript event="rowSelect" execute="onRowSelectedHandler();"/>
        ...
    </p:dataTable>
    ...
</html>

And that should be it, hope this helps...

0
votes

You can catch ajax events that are fired when the row is selected.

In your case,

<p:dataTable rowSelectListener="#{tableBean.onRowSelect}" 
    var="data" value="#{tableBean.data}" paginator="true" rows="10"
    selection="#{tableBean.selectedNames}">

    <p:ajax event="rowSelectCheckbox" listener="#{tableBean.handleEvent}" 
        update="buttonThatNeedsToBeRendered"/>

    <p:column selectionMode="multiple" />

    ...

</p:dataTable>

Other useful events that are fired depending on the selection mode of the dataTable are:

  1. rowSelect and rowUnselect
  2. rowSelectCheckbox and rowUnselectCheckbox
  3. rowSelectRadio
  4. toggleSelect