Dynamically enable/disable a commandButton on a Primefaces table row selection basis - jsf

Is there a way to dynamically enable/disable a commandButton on a table row selection basis?
In the next example, I want to enable ‘deleteBtn’ only if there is any row selected:
<p:dataTable
var="department" value="#{departmentCtrl.departmentTable}"
selection="#{departmentCtrl.departmentList}">
<p:column selectionMode="multiple" styleClass="w18" />
<p:column headerText="#{msgs.id}" sortBy="#{department.id}">
<h:outputText value="#{department.id}" />
</p:column>
<p:column headerText="#{msgs.name}" sortBy="#{department.name}">
<h:outputText value="#{department.name}" />
</p:column>
</p:dataTable>
<p:commandButton id="deleteBtn" value="#{msgs.delete}" disabled="???" />
Thanks

You should update your button every time a select or unselect event
occurs.
You should disable it when the departmentList is empty.
<p:dataTable var="department"
value="#{departmentCtrl.departmentTable}"
selection="#{departmentCtrl.departmentList}">
<p:ajax event="rowSelect" update="deleteBtn"/>
<p:ajax event="rowUnselect" update="deleteBtn"/>
<p:column selectionMode="multiple" styleClass="w18" />
<p:column headerText="#{msgs.id}" sortBy="#{department.id}">
<h:outputText value="#{department.id}" />
</p:column>
<p:column headerText="#{msgs.name}" sortBy="#{department.name}">
<h:outputText value="#{department.name}" />
</p:column>
</p:dataTable>
<p:commandButton id="deleteBtn" value="#{msgs.delete}"
disabled="#{fn:length(departmentCtrl.departmentList) == 0}" />
BTW don't forget to add the fn namespace to your facelets file.

A bit late to the party perhaps, but here is what it took for me to enable and disable based on every possible type of click in a Checkbox selection table. In my case I just needed to tell the Print and Delete buttons to disable when there was nothing selected.
<p:ajax event="rowSelect" update=":form:printBtn,:form:deleteBtn" />
<p:ajax event="rowUnselect" update=":form:printBtn,:form:deleteBtn" />
<p:ajax event="toggleSelect" update=":form:printBtn,:form:deleteBtn" />
<p:ajax event="rowSelectCheckbox" update=":form:printBtn,:form:deleteBtn" />
<p:ajax event="rowUnselectCheckbox" update=":form:printBtn,:form:deleteBtn" />
It is possible that you don't actually need all five events but I did. rowSelect and rowUnselect handled the mouse clicks that are not in the checkboxes. toggleSelect handles the checkbox that selects all/none (the one in the column headers) and the rowSelectCheckbox and rowUnselectCheckbox handle the checkboxes in the rows.

I am too late to response. But it might help someone. I got the same requirement to disable the button, when the user does not select any checkbox.
I am using Primefaces 5.1
Here is my proposed solution.
I am using widgetVar to check the selected row count and enable/disable the command button.
From the Primefaces document we have client side API for the data table:
Also we have client side API for command button
Now we will come back to the implementation part
<p:dataTable var="line" varStatus="loop"
value="#{myexpense.lazyModel}" paginator="true"
rows="#{myexpense.rows}"
rendered="#{myexpense.userIdSearch eq null}"
rowIndexVar="row"
emptyMessage="#{tk.expense_table_empty}"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink}
{PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
widgetVar="expenseEntryTable"
rowsPerPageTemplate="#{myexpense.rowsPerPageTemplate}"
id="lazyDataTable" lazy="true"
selection="#{myexpense.selectedExpenseEntryList}"
rowKey="#{line.oid}">
<p:ajax event="toggleSelect" oncomplete="disableOrEnableCommandButton();" update="updateBtn"/>
<p:ajax event="rowSelectCheckbox" oncomplete="disableOrEnableCommandButton();" update="updateBtn"/>
<p:ajax event="rowUnselectCheckbox" oncomplete="disableOrEnableCommandButton();" update="updateBtn"/>
<p:column selectionMode="multiple" width="3%" styleClass="centerAlignColumn selectAll" id="selectAll"/>
.... more column
<f:facet name="footer">
<p:commandButton process="lazyDataTable" value="#{tk.expense_update_selected}" partialSubmit="true" ajax="true" widgetVar="updateBtn" disabled="#{myexpense.disableUpdateButton}"
actionListener="#{myexpense.updateSelected}"
update="lazyDataTable #form" rendered="#{myexpense.form.myOnly}" />
</f:facet>
</p:dataTable>
As you can see I have defined 2 widgetVar, one for data table (expenseEntryTable) and another one for command button (updateBtn).
Also I have defined disbaled attribute #{myexpense.disableUpdateButton}, which will be helpful when the page load.
private Boolean disableUpdateButton;
public Boolean getDisableUpdateButton(){
disableUpdateButton = !((selectedExpenseEntryList!=null) && (!selectedExpenseEntryList.isEmpty()));
return disableUpdateButton;
}
Now you can write the java script.
function disableOrEnableCommandButton() {
if (PrimeFaces.widgets['expenseEntryTable']) {
if (PF('expenseEntryTable').getSelectedRowsCount() > 0) {
PF('updateBtn').enable();
} else {
PF('updateBtn').disable();
}
}
}
Hope it helps anyone!!!

[SOLVED]
In the manage bean I change from:
List departmentList;
to
Department[ ] departmentList;
Then I can use:
<p:ajax event="rowSelectCheckbox" listener="#{departmentCtrl.departmentSelected}"
update=":formManageDepartment:departmentBtnPanel,:formManageDepartment:deleteDepartmentBtn"/>
<p:ajax event="rowUnselectCheckbox" listener="#{departmentCtrl.departmentUnselected}"
update=":formManageDepartment:departmentBtnPanel,:formManageDepartment:deleteDepartmentBtn"/>

Related

p:dataTable unselect row without using meta key (selecting works)

I'm using:
Server: Wildfly 8.2
JSF: 2.2
Primefaces: 5.2
JDK:8
I have a datatable with multiple selection. I use rowSelectMode='add' so clicking on different rows without modifier keys adds new rows instead of unselecting all selected ones.
<p:dataTable id="table"
value="#{ixController.files}"
var="item" paginatorTemplate="{FirstPageLink} {PreviousPageLink}
{PageLinks}
{NextPageLink} {LastPageLink}"
selection="#{ixController.selecteds}"
rowKey="#{item.id}"
rowSelectMode="add"
selectionMode="multiple">
<p:column headerText="Files">
#{item.fileName}
</p:column>
As stated it works fine for adding rows, however I need to press Ctrl to unselect rows, and the customers wish to just click again on the row and unselect it.
Is that possible somehow?
Use check box instead that way they can select and un-select just by clicking it, follow Prime Faces example:
<p:dataTable id="checkboxDT" var="car" value="#{dtSelectionView.cars6}" selection="#{dtSelectionView.selectedCars}" rowKey="#{car.id}" style="margin-bottom:0">
<f:facet name="header">
Checkbox
</f:facet>
<p:column selectionMode="multiple" style="width:16px;text-align:center"/>
<p:column headerText="Id">
<h:outputText value="#{car.id}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Brand">
<h:outputText value="#{car.brand}" />
</p:column>
<p:column headerText="Color">
<h:outputText value="#{car.color}" />
</p:column>
<f:facet name="footer">
<p:commandButton process="checkboxDT" update=":form:multiCarDetail" icon="ui-icon-search" value="View" oncomplete="PF('multiCarDialog').show()" />
</f:facet>
</p:dataTable>
I cant find an attiribute for this, however, there is a way:
<p:dataTable value="#{groupBean.groups}" var="grp" rowKey="#{grp.id}"
selectionMode="single" selection="#{groupBean.group}">
<p:ajax event="rowSelect" listener="#{groupBean.onRowSelect}" update="#all" />
As you see, when a row clicked, selectedItem setted to groupBen.goup object.
public void onRowSelect(SelectEvent event) {
if (prevGroupId == group.getId())
group = new PersonelGroup();
else
prevGroupId = group.getId();
}
In onRowSelect method, you can check if user click same row for the second time by comparing previous selected item id. And by instanciating group object to new, DataTable has been updated to no selection state.
It is important to not forget to add update="#all" attiribute of DataTable.

How to refresh a row in Primefaces?

In a Primefaces <p:dataTable>, on each row, I have a column containing a commandButton.
This commandButton update a value of the bean corresponding to the current row.
How to refresh the current row where I have just clicked so that the reader column will refresh?
<p:dataTable id="repositoryBean"
currentPageReportTemplate="Total : {totalRecords}"
lazy="true"
resizableColumns="false"
rows="200"
rowsPerPageTemplate="10,15,20"
sortBy="#{row.name}"
sortOrder="ascending"
style="margin:20px 0px;"
value="#{repositoryBean.users}"
var="row"
styleClass="small-datatable"
editable="true"
>
<p:ajax event="rowSelect" listener="#{repositoryBean.onDisplay}"
onstart="PF('loading').show()"
/>
<p:column headerText="#{label.cvs_repo_user_firstname}" sortBy="#{row.firstname}" sortOrder="ascending">
<h:outputText value="#{row.firstname}" />
</p:column>
<p:column headerText="#{label.cvs_repo_user_is_reader}" sortBy="#{row.reader}" sortOrder="ascending">
<h:outputText value="#{row.reader}" />
</p:column>
<p:column headerText="#{label.cvs_repo_user_action}" style="text-align:center" >
<p:commandButton
value="Reader"
styleClass="btn-off"
action="#{repositoryBean.onSetReader(row)}"
/>
</p:column>
</p:dataTable>
Use the Omnifaces utility library for this. It has 'Ajax' functionality to update rows of a datatable and even has a specific PrimeFaces example.
It works like:
Ajax.updateRow(table, index);
where table is the reference to the component (not id!, but via binding) and index is the row index.

Can't select checkbox in primefaces datatable using selection

I have a dataTable in primefaces and wish to select multiple rows, but the checkbox doesn't highlight when I hover over it and can't be selected when I click.
The checkbox is definitely enabled. Here is the code:
<p:dataTable id="deferDatatable2"
value="#{deferMaintenanceTasksBean.tasksList}"
var="tasks"
rowKey="tasks.jobId"
selection="#{deferMaintenanceTasksBean.maintenanceTaskDatas}"
styleClass="editable-datatable" >
<p:ajax event="toggleSelect"
listener="#{deferMaintenanceTasksBean.toggleSelect()}" />
<p:ajax event="rowSelectCheckbox"
update="deferDatatable2" />
<p:ajax event="rowUnselectCheckbox"
update="deferDatatable2" />
<p:ajax event="rowSelect"
update="deferDatatable2" />
<p:ajax event="rowUnselect"
update="deferDatatable2" />
<p:column styleClass="select-column"
rendered="#{tasks.task.deferrable == 'true'}"
selectionMode="multiple" >
</p:column>
<p:column headerText="Task Code"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.task.taskCode}" />
</p:column>
<p:column headerText="Job Code"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.jobCode.code}" />
</p:column>
<p:column headerText="Description"
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText value="#{tasks.task.description}" />
</p:column>
<p:column headerText="Safety Critical"
rendered="#{tasks.task.deferrable == 'true'}">
<p:selectBooleanCheckbox value="#{tasks.task.safetyCritical}"
disabled="true" />
</p:column>
<p:column headerText="Deferrable?"
rendered="#{tasks.task.deferrable == 'true'}">
<p:selectBooleanCheckbox value="#{tasks.task.deferrable}"
disabled="true" />
</p:column>
<p:column headerText="Att."
rendered="#{tasks.task.deferrable == 'true'}">
<h:outputText id="i4AttachmentOutLbl"
value="#{tasks.task.attachmentCount}" />
</p:column>
</p:dataTable>
Inside the toggleSelect method there is just a log so I could see if the method is being called even though the checkboxes aren't being checked, but it isn't.
Like I say, the checkboxes all render as does everything else, and they aren't faded as if they were disabled, but they behave as if they were disabled. I have tried removing the styleClasses to see if they were somehow affecting things, but they aren't.
I have other working examples of this within my project and from what I can see I have set this dataTable up exactly the same, but for some reason it isn't working. The xhtml has the same ui:compposition and same outputStylesheets and outputScripts as these other pages and same basic layout, so I am convinced there is something I have missed from the dataTable, but no clue what.
I have added a little test table as follows with a list of strings called testList and this has worked. Not sure why this could be...
<p:dataTable id="testTable"
value="#{deferMaintenanceTasksBean.testList}"
var="test"
rowKey="test"
selection="#{deferMaintenanceTasksBean.testListSelect}">
<p:ajax event="toggleSelect"
listener="#{deferMaintenanceTasksBean.toggleSelect(1)}" />
<p:ajax event="rowSelectCheckbox"
update="testTable" />
<p:ajax event="rowUnselectCheckbox"
update="testTable" />
<p:ajax event="rowSelect"
update="testTable" />
<p:ajax event="rowUnselect"
update="testTable" />
<p:column selectionMode="multiple" />
<p:column>
<h:outputText value="#{test}" />
</p:column>
</p:dataTable>
Any suggestions appreciated.
Thanks
The removal of the rendered tags in your columns should then allow you to select the check boxes. I presume this is because it removes the top of your table and the toggle all check box causing the rest to fail silently

Unable to process expanded row data in primefaces datatable

This is my xhtml code containing a datatable using row expansion. Using primefaces 4.0, jsf mozarra 2.2.4
<p:dataTable id="myTable" value="#{myBean.lazyModel}" var="dd"
rowKey="#{dd.hashCode()}" paginator="true"
selection="#{myBean.myModel.selectedRecords}" rows="#{myBean.pageSize}"
paginatorPosition="top"
paginatorTemplate="{CurrentPageReport} {FirstPageLink}
{PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
rowsPerPageTemplate="5,10,20,50,100" widgetVar="dataTable"
currentPageReportTemplate="(Number of Records: {totalRecords})"
lazy="true">
<p:ajax event="rowToggle" listener="#{myBean.onRowToggle}" process="#this"/>
<p:column>
<p:rowToggler />
</p:column>
<p:column selectionMode="multiple" id="select" />
<p:column id="cpn" headerText="#{messages['cpn']}"
filterMatchMode="contains" sortBy="#{dd.cpn}" filterBy="#{dd.cpn}">
<p:inputText id="cpnid" value="#{dd.cpn}" />
</p:column>
<p:column id="user" headerText="#{messages['user']}"
filterMatchMode="contains" sortBy="#{dd.number}"
filterBy="#{dd.number}">
<p:inputText id="addid" value="#{dd.number}" />
</p:column>
:
:
<p:rowExpansion id="rowExpansion">
<p:panelGrid>
<p:row>
<p:column>
<h:outputText value="#{messages['name']}" />
</p:column>
<p:column>
<p:inputText id="name" name="txtBox" value="#{dd.name}" />
</p:column>
<p:column>
<h:outputText value="#{messages['ageGroup']}" />
</p:column>
<p:column id="agecol">
<p:selectOneMenu id="agegrp" value="#{dd.agegrp}">
<f:selectItem itemLabel="21-25" itemValue="21-25" />
<f:selectItem itemLabel="26-30" itemValue="26-30" />
</p:selectOneMenu>
</p:column>
</p:row>
</p:panelGrid>
</p:rowExpansion>
</p:dataTable>
Now I expanded a row and entered name and selected age group and collapsed the row. If I reexpand the same row I couldn't see the values I have entered. When I debugged on collapsing the row The name field and age grp fields setters are called with null parameters.
If I remove the ajax rowToggle event then there is no request is sent to the server on row collapse.
All the examples I found are showing only static data on row expansion.
Is there any way to process data user entered on row collapse?
Any help is highly appreciated.
I had the same problem. Do you use this datatable in a dialog?
Try set dynamic=false in parent dialog.
Dynamic dialog may override your ajax request
Try to add <p:ajax partialSubmit="true" /> inside each input forms
Just remove sortBy from child table.
It's works to me.
Or,
In xhtml file (MasterDataTable):
<p:ajax event="rowToggle" listener="#{superView.ontoggle()}" />
On View file:
public void ontoggle() {
UIComponent table = FacesContext.getCurrentInstance().getViewRoot().findComponent("form:MasterDataTable:ChildDataTable");
if (table != null) {
table.setValueExpression("sortBy", null);
}
}

p:datatable multiple select with checkboxes. Rowtoggler triggers event

I have a datatable inside another datatable. The nested table I need to have a multiple selection checkboxes, a button to fire actionlistener and a p:rowToggler to show more data in row. The toggler and commandbutton works fine without the selection column in the table, but when I add this column the commandButton doesn't go to the backing bean, toggler on click doesn't work properly, and setSelected isn't called. Both throw a NP. I'm using 3.4.2 is this feature on newer releases only?
SEVERE: FullAjaxExceptionHandler: An exception occurred during processing JSF ajax request. Error page '/error.xhtml' will be shown.
java.lang.NullPointerException
Table
<p:dataTable id="gro" var="g" value="#{requestBean.main.childRequest}" styleClass="veaGrid"
paginator="true" rows="1" paginatorTemplate="{CurrentPageReport}" >
<p:column>
<p:ajaxStatus >
<f:facet name="start">
<p:graphicImage value="/resources/images/ajaxloadingbar.gif" />
</f:facet>
<f:facet name="complete">
<h:outputText value="" />
</f:facet>
</p:ajaxStatus>
<p:dataTable id="group" var="g2" value="#{g.groups}" rowKey="#{g2.group_name}" selection="#{requestBean.selectedGroups}" >
<p:column selectionMode="multiple" style="width:2%" />
<p:column headerText="#{g.systemCd} - Groups" style="width:25%" >
#{g2.group_name}
</p:column>
<p:column style="width:2%">
View Users <p:rowToggler />
</p:column>
<p:rowExpansion>
<p:dataTable styleClass="veaGrid" var="g3" value="#{g2.group_members}" sortOrder="descending"
paginator="true" rows="10"
paginatorTemplate="{CurrentPageReport} {FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}"
filteredValue="#{requestBean.filteredMembers}">
<p:column filterBy="#{g3.first_name}">
<h:outputText value="#{g3.first_name}"/>
</p:column>
<p:column filterBy="#{g3.last_name}">
<h:outputText value="#{g3.last_name}"/>
</p:column>
<p:column filterBy="#{g3.signon}">
<h:outputText value="#{g3.signon}"/>
</p:column>
</p:dataTable>
</p:rowExpansion>
</p:dataTable>
<center>
<p:commandButton id="continue" value="Continue" actionListener="#{requestBean.saveGroups}"/>
</center>
</p:column>
</p:dataTable>
Found the problem.. I had the requestBean.selectedGroups set to
ArrayList<Group>
I changed the property to
Group[]
and now everything is functional again.

Resources