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.
Related
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.
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);
}
}
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.
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"/>
RadioButton/Checkbox based row selection is a common use case and DataTable provides a solution for this with column selection mode feature.
<p:dataTable var="car" value="#{tableBean.cars}" paginator="true" rows="10"
selection="#{tableBean.selectedCar}">`
<f:facet name="header">
RadioButton Based Selection
</f:facet>
<p:column selectionMode="single" />
<p:column headerText="Model">
<h:outputText value="#{car.model}" />
</p:column>
<p:column headerText="Year">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Manufacturer">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<f:facet name="footer">
<p:commandButton value="View" image="ui-icon ui-icon-search"
update="displaySingle" oncomplete="singleCarDialog.show()"/>
</f:facet>
</p:dataTable>
I want to know if I choose the first column's radioButton ,how I get a event for this.
Because I want to let a button disabled when choose the first column or the last column's radioButton .
And I also want to get the index of the column when selected the column ,Now I use the selectedCar to compare the list,and get the index of the column. It looks ugly.Anyone can help me ?
This is a solution for PrimeFaces <= 2.x only.
There is a good example at Primeface's showcase. There is an attribute rowSelectListener that can be used like this:
rowSelectListener="#{tableBean.onRowSelect}"
and in the backing bean:
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("Car Selected",
((Car) event.getObject()).getModel());
FacesContext.getCurrentInstance().addMessage(null, msg);
}