RadioButton row select event in p:datatable - jsf

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);
}

Related

Way to store variable in JSF / issue with c:set and ui:param

I tried c:set and ui:param, but in the end I think I did something wrong.
Here is the crucial XHTML part:
<h:form id="formTable">
<p:dataTable editable="true" value="#{types.dataList}" var="datalist" style="width:90%; margin-bottom:20px"
rows="10" paginator="true" rowsPerPageTemplate="10,25" resizableColumns="true" liveResize="true" tableStyle="width:auto">
<!-- save the old value for the edit action-->
<c:set var="oldValue" value="#{datalist.getType()}"/>
<!-- column for testing purpose-->
<p:column>
<h:outputText value="#{oldValue}" />
</p:column>
<p:column headerText="Type" sortBy="#{datalist.type}">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{datalist.type}" />
</f:facet>
<f:facet name="input">
<h:inputText value="#{datalist.type}" binding="#{inputUpdateType}" required="true" />
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Date" sortBy="#{datalist.lastModifyDate}">
<h:outputText value="#{datalist.lastModifyDate}"/>
</p:column>
<p:column headerText="Edit">
<p:rowEditor rendered="#{!datalist.dependenciesFound}"/>
<h:graphicImage value="../images/attention.png" rendered="#{datalist.dependenciesFound}" />
</p:column>
<p:column headerText="Delete">
<p:commandLink action="#{types.delete(datalist.type)}" rendered="#{!datalist.dependenciesFound}" update=":formTable">
<p:graphicImage url="../images/delete.png" />
<p:confirm header="Confirmation" message="Are you sure?" icon="ui-icon-alert" />
</p:commandLink>
<h:outputText value="Not editable because of dependency" rendered="#{datalist.dependenciesFound}"/>
</p:column>
<!-- We edit/update the value here. This is where the old value is needed-->
<p:ajax event="rowEdit" listener="#{types.update(oldValue, inputUpdateType.value)}"/>
</p:dataTable>
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade">
<p:commandButton value="Yes" type="button" styleClass="ui-confirmdialog-yes" icon="ui-icon-check" />
<p:commandButton value="No" type="button" styleClass="ui-confirmdialog-no" icon="ui-icon-close" />
</p:confirmDialog>
</h:form>
I hope this is somewhat understandable.
For my project I use Primefaces 6.1. To edit a row in this table I need to save the old value and use that value in the ajax call at the bottom. I need this, because the application or rather the DB table behind this demands it (id is this value).
The edited value is stored in the variable inputUpdateType.
My problem:
When I enter a new value and hit edit, the old value is the same as the edited value, when the application enters the update method. I made a log entry in my update method to verify what values are passed. Same with c:set and ui:param.
What am I doing wrong? How can I make this work?
EDIT:
Here is how I try to get the old value stored in my bean:
<p:ajax event="rowEdit" listener="#{types.update(types.dataListOld.toArray()[rowIndex].getType(), inputUpdateType.value)}"/>
So, it seems with ajax the values will be updated before executing the method. Therefore the old value is not available on server side anymore. Unfortunately storing the variable in JSF is also not possible because c:set will be processed before the JSF tags and will thus not hold any values (without a scope it will act as an alias and in the end also been updated before the method gets executed).
To make this whole thing work I used cell edit mode instead of the default row edit mode. With this I'm able to get the old and new value:
public void onCellEdit(CellEditEvent event){
//We will call this method on edits made to a cell
//Values are stored in a Arraylist. Number of entries depend on how many components there are in the edited cell/facet
//Here we have two because in "input" there are two components defined (although both are rendered at the same time).
#SuppressWarnings("unchecked")
ArrayList<String> oldValue = ((ArrayList<String>)(event.getOldValue()));
#SuppressWarnings("unchecked")
ArrayList<String> newValue = ((ArrayList<String>)(event.getNewValue()));
//In the end both entries have the same value, so we just take the first.
if(newValue != null && !newValue.equals(oldValue)) {
update(oldValue.get(0), newValue.get(0));
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue.get(0) + ", New:" + newValue.get(0));
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
Here is why I have two entries in my values list (two components in "input"):
<f:facet name="input">
<h:inputText value="#{datalist.type}" binding="#{inputUpdateType}" required="true" rendered="#{!datalist.dependenciesFound}"/>
<h:outputText value="#{datalist.type}" rendered="#{datalist.dependenciesFound}"/>
</f:facet>
</p:cellEditor>

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.

Primefaces datatable multiple selection row count

Firstly im sorry my english it is not my orginal language. I have a primefaces datatable and in multiple selection mode.
<h:form id="form">
<p:panel>
<p:tabView activeIndex="#{logoDocumentIntegration.tabIndex}" >
<p:tab title="Aktarilmayan Musteriler">
<p:dataTable id="notTransfaredClient" rows="10" value="#{logoDocumentIntegration.notTransfaredClientList}" selection="#{logoDocumentIntegration.selectedTransfaredClientList}" rowKey="#{cl.clientId}" var="cl" >
<p:column selectionMode="multiple" style="width:16px;text-align:center"/>
<p:column headerText="Id" style="width:2%" rendered="false">
<h:outputText value="#{cl.clientId}" />
</p:column>
<p:column headerText="TCNo" style="width:2%">
<h:outputText value="#{cl.taxNo}" />
</p:column>
<p:column headerText="İsim" style="width:2%">
<h:outputText value="#{cl.name}" />
</p:column>
<p:commandButton id="test" value="Ekle" actionListener="#{logoDocumentIntegration.transferClient(logoDocumentIntegration.selectedTransfaredClientList)}" />
I want to get selection row count from datatable.For this i used to a arraylist its name is selectedLis.In managedbean i have this line:
private List<ClientView> selectedTransfaredClientList = new ArrayList<ClientView>();
public List<ClientView> getSelectedTransfaredClientList() {
return selectedTransfaredClientList;
}
public void setSelectedTransfaredClientList(List<ClientView> selectedTransfaredClientList) {
this.selectedTransfaredClientList = selectedTransfaredClientList;
}
Everything is okay but when i want to get selectedTransferedClientList count is returning 0.Where is my mistake thank you so much for your reply.

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);
}
}

Reload <p:tab> info with <p:commandButton> action

I have a <p:tabView> with 2 tabs. The first one contains student details and the second one contains a table of all students.
<p:tab title="List">
<p:dataTable id="studentsTable" value="#{studentMB.allStudents}" var="student">
<p:column>
<f:facet name="header"><h:outputText value="ID"/></f:facet>
<h:outputText value="#{student.id}"/>
</p:column>
<p:column>
<f:facet name="header"><h:outputText value="Name"/></f:facet>
<h:outputText value="#{student.name}"/>
</p:colum>
<p:column>
<p:commandButton value="Details" onclick="tabVar.select(0);" />
</p:column>
</p:dataTable>
</p:tab>
When the "Details" button in the table is pressed, then I would like to show the selected student in the first tab. How can I achieve this?
Primefaces tabview has activeIndex attribute, you can bind to bean variable:
<p:tabView id="tabView" activeIndex="#{studentMB.tabindex}">
In each commandButton action, you pass value to determine student.
<p:commandButton update=":tabView" value="Details" actionListener="#{studentMB.handUpdate(student)}" />
Bean:
public void handUpdate(StudentType stValue){
// get student detail
}
(Sorry for my english)

Resources