I got a problem described in the title. My selectOneMenu doesn't change my Value :/
<h:column>
<f:facet name="header">
<h:outputText value="Vorgesetzter" />
</f:facet>
<h:outputText
value="#{s.manager.surename}, #{s.manager.forename}"
rendered="#{not s.editable}" />
<h:selectOneMenu value="#{s.manager.userID}"
styleClass="inputlabel" id="Vorgesetzter"
rendered="#{s.editable}">
<f:selectItem
itemValue="${null}" itemLabel="-"/>
<f:selectItems value="#{userBean.userList}" var="us"
itemLabel="#{us.surename}, #{us.forename}"
itemValue="#{us.userID}" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:commandButton value="bearbeiten"
action="#{sectionBean.switchEdit(s)}"
rendered="#{not s.editable}" />
<h:commandButton value="speichern"
action="#{sectionBean.updateSection(s)}"
rendered="#{s.editable}" />
<h:commandButton value="abbrechen"
action="#{sectionBean.switchEdit(s)}"
rendered="#{s.editable}" />
</h:column>
this is a piece of the sections.xhtml. It's sourrounded by a form tag.
This is my bean:
package at.ac.htlperg.beans;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import at.ac.htlperg.dao.SectionDAO;
import at.ac.htlperg.model.Section;
#ManagedBean
#SessionScoped
public class SectionBean {
SectionDAO sectionDAO;
public SectionBean() {
sectionDAO = new SectionDAO();
}
public SectionDAO getSectionDAO() {
return sectionDAO;
}
public void setSectionDAO(SectionDAO sectionDAO) {
this.sectionDAO = sectionDAO;
}
public List<Section> getSectionList() {
return sectionDAO.getSectionList();
}
public String deleteSection(Section s) {
sectionDAO.deleteSection(s);
return null;
}
public String switchEdit(Section s) {
sectionDAO.switchEdit(s);
return null;
}
public String saveSection() {
sectionDAO.saveSection(sectionDAO.getSection());
return "/secured/sealed/sections.xhtml";
}
public String updateSection(Section s) {
sectionDAO.updateSection(s);
this.switchEdit(s);
return null;
}
}
the method updateSection should access the Database and does an session.update(s).
But it doesn't save the new values, neither in the selectOneMenu, nor in the usual textbox above (not in the shown code).
Anyone knows what's wrong?
Don't know if it helps, but in JSF 1.2 I had similar issues. The Problem was that h:selectOneMenu returned String values instead of Objects I suspected.
Maybe this "bug" wasn't solved for JSF2.0.
try something like:
// ManagedBean
String userId;
String getUserId(){return this.userId;}
void setUserId(String userId){this.userId = userId;}
// JSF
<h:selectOneMenu value="#{managedBean.userId}"
styleClass="inputlabel" id="Vorgesetzter"
rendered="#{s.editable}">
<f:selectItems value="#{userBean.userList}" var="us"
itemLabel="#{us.surename}, #{us.forename}"
itemValue="#{us.userID}" />
</h:selectOneMenu>
and before working with userId convert it into the Object you want, or just try to use a converter.
Related
This question already has answers here:
How to dynamically add JSF components
(3 answers)
Closed 6 years ago.
I am trying to add h:inputText and a selectOneMenu dynamically in jsf2. And I got success in that. Now the new problem is that, when I clicked "Add New" button, previously dynamically added h:inputText value is erased. And I don't want that to happen. My code is below. Please help. :)
<h:form>
<h:dataTable id="bankAccountDataTable" value="#{kycBeanJSF.kycDataModelJSF.kycdto.bankAccountInfoDTOs}" var="item" binding="#{kycBeanJSF.htmlDataTable}">
<h:column>
<label class="label-control"><p:outputLabel value="आबेदकको बैंक खाता नम्बर:"/><span class="required">*</span></label>
<h:inputText value="#{item.bankAccountNumber}"/>
</h:column>
<h:column>
<h:selectOneRadio id="radio1" value="#{item.bankAccountType}" layout="lineDirection" >
<f:selectItem itemLabel="चल्ती खाता" itemValue="chalti" />
<f:selectItem itemLabel="बचत खाता" itemValue="bachat" />
<f:selectItem itemLabel="कॉल खाता" itemValue="call" />
</h:selectOneRadio>
</h:column>
<h:column>
<h:commandButton value="Remove" action="#{kycBeanJSF.kycWebCoreBean.remove(item)}" immediate="true"/>
</h:column>
</h:dataTable>
<h:commandButton value="Add New" action="#{kycBeanJSF.kycWebCoreBean.addNew()}" immediate="true"/>
</h:form>
My KycBeanJSF is in Request Scope. KycDataModelJSF is in SessionScope.
KycBeanJSF.java
public class KycBeanJSF {
#ManagedProperty(value = "#{kycDataModelJSF}")
private KycDataModelJSF kycDataModelJSF;
private KycWebCoreBean kycWebCoreBean;
#PostConstruct
public void initWebCore(){
kycWebCoreBean = new KycWebCoreBean();
}
//getters and setters
}
KycDataModelJSF.java
#ManagedBean(name = "kycDataModelJSF")
#SessionScoped
public class KycDataModelJSF {
private KYCDTO kycdto;
#PostConstruct
public void init(){
addNew();
}
public KYCDTO getKycdto() {
if (kycdto == null) {
kycdto = new KYCDTO();
}
return kycdto;
}
public void setKycdto(KYCDTO kycdto) {
this.kycdto = kycdto;
}
public void addNew() {
if(getKycdto().getBankAccountInfoDTOs().size()<3){
getKycdto().getBankAccountInfoDTOs().add(new BankAccountInfoDTO());
}
else if(getKycdto().getBankAccountInfoDTOs().size()>=3){
FacesUtil.setErrorFacesMessage("Sorry, cannot add more than three accounts.");
}
}
}
KycWebCoreBean.java
public class KycWebCoreBean {
private KycDataModelJSF kycDataModelJSF;
public KycWebCoreBean() {
kycDataModelJSF = (KycDataModelJSF) Util.getSessionObject("kycDataModelJSF");
kycDependencyInjection = (KycDependencyInjection) Util.getSessionObject("kycDependencyInjection");
applicantRegisterDataModelJSF = (ApplicantRegisterDataModelJSF) Util.getSessionObject("applicantRegisterDataModelJSF");
}
public void addNew() {
if(kycDataModelJSF.getKycdto().getBankAccountInfoDTOs().size()<3){
kycDataModelJSF.getKycdto().getBankAccountInfoDTOs().add(new BankAccountInfoDTO());
}
else if(kycDataModelJSF.getKycdto().getBankAccountInfoDTOs().size()>=3){
FacesUtil.setErrorFacesMessage("Sorry, cannot add more than three accounts.");
}
}
public void remove(BankAccountInfoDTO b) {
kycDataModelJSF.getKycdto().getBankAccountInfoDTOs().remove(b);
}
}
I will provide more Info if required.
Thanks In Advance.
As h:inputText can store only one value, I assume that you want to append new value to old. If so, than in bean which manages that property in setter method use
public void setValue(String value) {
this.value = this.value + " " + value;
}
instead of usual
public void setValue(String value) {
this.value = value;
}
With string "my string" in h:inputText after changing value to "another string" result is "my string another string"
<h:dataTable id="bankAccountDataTable" value="#{kycBeanJSF.kycDataModelJSF.kycdto.bankAccountInfoDTOs}" var="item">
<h:column>
<label class="label-control"><p:outputLabel value="आबेदकको बैंक खाता नम्बर:"/><span class="required">*</span></label>
<h:inputText value="#{item.bankAccountNumber}"/>
</h:column>
<h:column>
<h:selectOneRadio id="radio1" value="#{item.bankAccountType}" layout="lineDirection">
<f:selectItem itemLabel="चल्ती खाता" itemValue="chalti" />
<f:selectItem itemLabel="बचत खाता" itemValue="bachat" />
<f:selectItem itemLabel="कॉल खाता" itemValue="call" />
</h:selectOneRadio>
</h:column>
<h:column>
<h:commandButton value="Remove" actionListener="#{kycBeanJSF.kycWebCoreBean.remove(item)}">
<f:ajax render="#form"/>
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="Add New" actionListener="#{kycBeanJSF.kycWebCoreBean.addNew()}">
<f:ajax execute="bankAccountDataTable" render="bankAccountDataTable msg"/>
</h:commandButton>
I would like to have a 'Show All' button for a primefaces datatable, however, I'm experiencing some trouble. Here's some test code that demostrates the problem:
Test.xhtml:
...
<h:form>
<p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
<p:ajax update="#form"/>
</p:selectBooleanCheckbox>
<p:panel id="test">
<p:dataTable id="values" var="value" value="#{testBean.fullList}" filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false"
paginator="#{!testBean.showAll}" rows="#{!testBean.showAll ? 2 : null }" widgetVar="valuesTable"
emptyMessage="No records found.">
<p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Enum" />
</f:facet>
<h:outputText value ="#{value.toString()}"/>
</p:column>
<p:column id="name" sortBy="#{value.name}" filterBy="#{value.name}" filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{value.name}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
...
And here's TestBean.java:
import javax.inject.Named;
import javax.enterprise.context.SessionScoped;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
#Named(value = "testBean")
#SessionScoped
public class TestBean implements Serializable {
public static enum Value {
ONE, TWO, THREE;
public String getName() {
return name().toLowerCase();
}
#Override
public String toString() {
return this.name();
}
}
/**
* Creates a new instance of TestBean
*/
public TestBean() {
}
private boolean showAll = false;
private List<Value> fullList = Arrays.asList(Value.values());
private List<Value> filteredList;
public boolean isShowAll() {
return showAll;
}
public void setShowAll(boolean showAll) {
this.showAll = showAll;
}
public List<Value> getFullList() {
return fullList;
}
public void setFullList(List<Value> fullList) {
this.fullList = fullList;
}
public List<Value> getFilteredList() {
return filteredList;
}
public void setFilteredList(List<Value> filteredList) {
this.filteredList = filteredList;
}
}
If I don't change tabs, the page works as expected: toggling the 'Show All' button updates the table to show all 3 values, or only two. However, if show all is not checked (only 2 rows are showing), and I click to the 2nd page of the table to view the third record, and then click 'Show All', the table does not update properly. It removes the paginator from the top of the table (as expected), but still only shows the 3rd record. And if I then uncheck show all and navigate back to the first page of the datatable, it is now broken too.
I've tried changing the ajax update statement to the id of the table, but that didn't change the results.
Am I doing something wrong? Thanks in advance.
You have to programmatically set the values you need directly on the DataTable component (I used explicit first and rows bean properties just for more readability):
<h:form>
<p:selectBooleanCheckbox value="#{testBean.showAll}" itemLabel="Show All">
<p:ajax update="#form" />
</p:selectBooleanCheckbox>
<p:panel id="test">
<p:dataTable id="values" var="value" value="#{testBean.fullList}"
filteredValue="#{testBean.filteredList}" paginatorAlwaysVisible="false"
paginator="#{!testBean.showAll}" first="#{testBean.first}" rows="#{testBean.rows}"
widgetVar="valuesTable" emptyMessage="No records found.">
<p:column id="enum" sortBy="#{value.toString()}" filterBy="#{value.toString()}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Enum" />
</f:facet>
<h:outputText value="#{value.toString()}" />
</p:column>
<p:column id="name" sortBy="#{value.name}" filterBy="#{value.name}"
filterMatchMode="contains">
<f:facet name="header">
<h:outputText value="Name" />
</f:facet>
<h:outputText value="#{value.name}" />
</p:column>
</p:dataTable>
</p:panel>
</h:form>
and
#Named
#ViewScoped
public class TestBean implements Serializable
{
private static final long serialVersionUID = 1L;
public static enum Value
{
ONE, TWO, THREE;
public String getName()
{
return name().toLowerCase();
}
#Override
public String toString()
{
return name();
}
}
private boolean showAll = false;
private int first = 0;
private int rows = 2;
private List<Value> fullList = Arrays.asList(Value.values());
private List<Value> filteredList;
public boolean isShowAll()
{
return showAll;
}
public void setShowAll(boolean showAll)
{
this.showAll = showAll;
first = 0;
rows = showAll ? 0 : 2;
filteredList = null;
// get the FacesContext instance
FacesContext context = FacesContext.getCurrentInstance();
// get the current component (p:selectBooleanCheckbox)
UIComponent component = UIComponent.getCurrentComponent(context);
// find DataTable within the same NamingContainer
DataTable table = (DataTable) component.findComponent("values");
// reset first row index
table.setFirst(first);
// reset last row index
table.setRows(rows);
// reset filterd value
table.setFilteredValue(null);
}
// all other getters/setters
}
Tested on Wildfly 10.0.0.Final with JSF 2.3.0-m06 (Mojarra) and PrimeFaces 6.0.2
I had the same problem, was resolved by this steps:
Adding styleClass="all-paginator" to datatable
<p:dataTable id="values" var="value" value="#{testBean.fullList}"
filteredValue="#{testBean.filteredList}" styleClass="all-paginator"..>
Add a getter of number of all records in the controller (TestBean.java) like:
public int getRecordNumber() {
if(CollectionUtils.isEmpty(fullList)){
return 0;
}
return fullList.size();
}
Add the property of the recordNumber at the end of the datatable attribute "rowsPerPageTemplate"
<p:dataTable id="values" var="value" value="#{testBean.fullList}" filteredValue="#{testBean.filteredList}"
styleClass="all-paginator" rowsPerPageTemplate="20,30,40,50,#{testBean.recordNumber}"..>
I'm using Spring, Hibernate and JSF for a web application.
In my case I have a Table User having many columns, one of those is idRole. idRole is a foreign key from table Role which containes Id of the role and the role name.
What I want to know is how to make the role name shown in my place of the ID, and make that field a List showing only possible roles (which are all the columns of the Roles table)
Here is my ManagedBean :
package managedController;
import org.primefaces.event.RowEditEvent;
import org.springframework.dao.DataAccessException;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import spring.model.Customer;
import spring.service.CustomerService;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
#ManagedBean(name="customerMB")
#RequestScoped
public class CustomerManagedBean implements Serializable {
private static final long serialVersionUID = 1L;
private static final String SUCCESS = "success";
private static final String ERROR = "error";
#ManagedProperty(value="#{CustomerService}")
CustomerService customerService;
List<Customer> customerList;
private int id;
private String name;
private String surname;
public String addCustomer() {
try {
Customer customer = new Customer();
customer.setId(getId());
customer.setName(getName());
customer.setSurname(getSurname());
getCustomerService().addCustomer(customer);
reset();
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
public String updateCustomer(Customer customer) {
try {
getCustomerService().updateCustomer(customer);
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
public String deleteCustomer(Customer customer) {
try {
getCustomerService().deleteCustomer(customer);
customerList = null;
getCustomerList();
return SUCCESS;
} catch (DataAccessException e) {
e.printStackTrace();
}
return ERROR;
}
public void onEdit(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Item Edited");
FacesContext.getCurrentInstance().addMessage(null, msg);
updateCustomer((Customer)event.getObject());
}
public void onCancel(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Item Cancelled");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void reset() {
this.setId(0);
this.setName("");
this.setSurname("");
}
public List<Customer> getCustomerList() {
if(customerList == null){
customerList = new ArrayList<Customer>();
customerList.addAll(getCustomerService().getCustomers());
}
return customerList;
}
public CustomerService getCustomerService() {
return customerService;
}
public void setCustomerService(CustomerService customerService) {
this.customerService = customerService;
}
public void setCustomerList(List<Customer> customerList) {
this.customerList = customerList;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
and here is the file where I show them (Users or Customers let's say) :
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
xmlns:sec="http://www.springframework.org/security/tags">
<h:head>
<title>Welcome</title>
</h:head>
<h:body>
<!-- View element level Spring Security : only can view for who has the role 'ROLE_ADMIN' -->
<sec:authorize access="hasAnyRole('ROLE_ADMIN')">
<h:form id="form2">
<table>
<tr>
<td><h:outputLabel for="id" value="Id : "/></td>
<td><p:inputText id="id" value="#{customerMB.id}">
<f:converter converterId="javax.faces.Integer"/>
<p:ajax event="blur" update="idMsg"/>
</p:inputText>
<p:message id="idMsg" for="id" display="icon"/>
</td>
</tr>
<tr>
<td><h:outputLabel for="name" value="Name : "/></td>
<td><p:inputText id="name" value="#{customerMB.name}">
<f:validateLength minimum="1"/>
<p:ajax event="blur" update="nameMsg"/>
</p:inputText>
<p:message id="nameMsg" for="name" display="icon"/>
</td>
</tr>
<tr>
<td><h:outputLabel for="surname" value="Surname : "/></td>
<td><p:inputText id="surname" value="#{customerMB.surname}">
<f:validateLength minimum="1"/>
<p:ajax event="blur" update="surnameMsg"/>
</p:inputText>
<p:message id="surnameMsg" for="surname" display="icon"/>
</td>
</tr>
<tr>
<td><p:commandButton id="addUser" value="Add" action="#{customerMB.addCustomer}" ajax="false"/></td>
<td><p:commandButton id="reset" value="Reset" action="#{customerMB.reset}" ajax="false"/></td>
</tr>
</table>
</h:form>
</sec:authorize>
<br/>
<h:form id="form1">
<p:growl id="messages" showDetail="true"/>
<p:dataTable id="customers" var="customer" value="#{customerMB.customerList}" style="width: 10%" editable="true">
<p:ajax event="rowEdit" listener="#{customerMB.onEdit}" update=":form1:messages"/>
<p:ajax event="rowEditCancel" listener="#{customerMB.onCancel}" update=":form1:messages"/>
<p:column headerText="ID">
<h:outputText value="#{customer.id}"/>
</p:column>
<p:column headerText="Name">
<f:facet name="header">
<h:outputText value="Name"/>
</f:facet>
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{customer.name}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{customer.name}" label="name"/>
</f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Surname">
<p:cellEditor>
<f:facet name="output">
<h:outputText value="#{customer.surname}"/>
</f:facet>
<f:facet name="input">
<p:inputText value="#{customer.surname}" label="surname"/>
</f:facet>
</p:cellEditor>
</p:column>
<sec:authorize access="hasAnyRole('ROLE_ADMIN')">
<p:column>
<f:facet name="header">Delete</f:facet>
<h:commandLink value="Delete" action="#{customerMB.deleteCustomer(customer)}"/>
</p:column>
<p:column style="width:20%">
<f:facet name="header">Update</f:facet>
<p:rowEditor/>
</p:column>
</sec:authorize>
</p:dataTable>
<br/>
<p:commandButton value="Logout" id="logout" action="#{loginBean.logout}"/>
</h:form>
</h:body>
</html>
Thank you
#ManagedBean(name="customerMB")
#RequestScoped
...
#ManagedProperty(value="#{CustomerService}")
CustomerService customerService;
It's advised to switch those to :
#Named
#RequestScoped
...
#Inject or #EJB
SomeService ss;
//for a managed property just use Inject without parameters.
Your code will still work. But take the javax.enterprise.context.RequestScoped package for request scoped.
Since you didn't post any entity whatsoever and probably copy pasted the tutorial, I'll post smtg generic to give you a general idea of how to go with it:
#Named
#RequestScoped
public class Mybean {
private List<User> userLists; // +getters and setters
#EJB
private SomeService ss;
//make the call to the Db in a PostConstruct annotated method, NOT in the constructor. So the injections are done.
#PostConstruct
public void init(){
userLists = ss.getUsers();
}
}
What I want to know is how to make the role name shown in my place of
the ID
Huh ? I guess you want this :
<h:dataTable value="#{mybean.userLists}" var="user">
<h:column>
#{user.role.name}
</h:column>
</h:dataTable>
In your entities you must have a relationship between the two. Probably #ManyToOne
and make that field a List showing only possible roles (which are all
the columns of the Roles table)
Same idea, get your list from db in the init method:
roleList = aService.getRoles();
Then You want to display those in a list ? I guess you meant a selectOneMenu. Follow the link the tutorial is well explained.
In my application I want to execute a client side method before expanding row of <p:dataTable> so I am using onExpandStart="alert('Helo');". But this also is not working for me.
.xhtml code snippet :
<p:dataTable value="#{ExampleDataModel}" lazy="true" paginator="true" onExpandStart="alert('Helo');">
<p:column id="rowToggle" styleClass="rowtoggle">
<p:rowToggler />
</p:column>
<p:rowExpansion>
..........
</p:rowExpansion>
</p:dataTable>
can anyone tell wher I have done wrong? I am using PF 3.4,Mojara(2). Thanks.
Update-1 :
managedBean's code snippet :
#ManagedBean(name = "columnController")
#ViewScoped
public class ColumnController implements Serializable {
private List<ColumnDTO> userNames;
public List<ColumnDTO> getUserNames() {
List<ColumnDTO> columns = new ArrayList<ColumnDTO>();
columns.add(new ColumnDTO(Integer.valueOf(1), "Diganta"));
columns.add(new ColumnDTO(Integer.valueOf(2), "Jayanta"));
columns.add(new ColumnDTO(Integer.valueOf(3), "Proloy"));
return columns;
}
public void setUserNames(List<ColumnDTO> userNames) {
this.userNames = userNames;
}
}
ColumnDTO.java :
public class ColumnDTO implements Serializable {
private static final long serialVersionUID = 4828438441215128064L;
private Integer columnId;
private String columnName;
public ColumnDTO(Integer index, String columnName) {
this.columnId = index;
this.columnName = columnName;
}
//...........getter setter
}
.xhtml code :
<h:head></h:head>
<body>
<h:form>
<p:dataTable value="#{columnController.userNames}" var="name" onExpandStart="alert('Hello')">
<p:column>
<p:rowToggler/>
</p:column>
<p:column>
<h:outputText value="#{name.columnName}" />
</p:column>
<p:rowExpansion>
<h:outputText value="#{name.columnId}" />
</p:rowExpansion>
</p:dataTable>
</h:form>
</body>
</html>
Try <p:ajax event="rowToggle" onstart="alert('Helo');"/> instead of onExpandStart
In the following scenario, where I have several dataTables that I build iterating over a ui:repeat tag, I have experienced that row listener returns null for selected elements that are not in the first table.
In order to understand the model object, I have several menus, and each of them contains several areas.
Any help will be much appreciated.
xhtml below:
<ui:repeat value="#{someBean.menus}" var="menu">
<p:dataTable var="area" value="#{menu.areas}"
rowKey="#{area.id}" selection="#{menu.area}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{someBean.rowSelected}" />
<f:facet name="header">#{menu.name}</f:facet>
<p:column>
<f:facet name="header"></f:facet>
<h:outputText value="#{area.id}" />
</p:column>
<p:column>
<f:facet name="header">Area name</f:facet>
<h:outputText value="#{area.name}" />
</p:column>
</p:dataTable>
</ui:repeat>
ListDataModel java implementation:
public class Areas extends ListDataModel<Area> implements SelectableDataModel<Area>, Serializable {
private static final long serialVersionUID = -9102592194300556930L;
public Areas() {
}
public Areas(List<Area> data) {
super(data);
}
#Override
public Area getRowData(String rowKey) {
#SuppressWarnings("unchecked")
List<Area> areas = (List<Area>)getWrappedData();
for (Area area : areas) {
if (String.valueOf(area.getId()).equals(rowKey)) {
return area;
}
}
return null;
}
#Override
public Object getRowKey(Area area) {
return area.getId();
}
}
public class Menus extends ListDataModel<Menu> implements SelectableDataModel<Menu>, Serializable {
private static final long serialVersionUID = -4079772686830676202L;
public Menus() {
}
public Menus(List<Menu> data) {
super(data);
}
#Override
public Menu getRowData(String rowKey) {
#SuppressWarnings("unchecked")
List<Menu> menus = (List<Menu>)getWrappedData();
for (Menu menu : menus) {
if (String.valueOf(menu.getId()).equals(rowKey)) {
return menu;
}
}
return null;
}
#Override
public Object getRowKey(Menu menu) {
return menu.getId();
}
}
...in the bean someBean
public void rowSelected(SelectEvent event) {
Area selectedArea = (Area)event.getObject(); //This, is null for other tables except the first
System.out.println("SELECTED AREA:" + selectedArea);
//...
}
I am glad to show you the solution: replace ui:repeat with another p:dataTable !!!
<p:dataTable value="#{someBean.menus}" var="menu">
<p:column>
<p:dataTable var="area" value="#{menu.areas}"
rowKey="#{area.id}" selection="#{menu.area}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{someBean.rowSelected}" />
<f:facet name="header">#{menu.name}</f:facet>
<p:column>
<f:facet name="header"></f:facet>
<h:outputText value="#{area.id}" />
</p:column>
<p:column>
<f:facet name="header">Area name</f:facet>
<h:outputText value="#{area.name}" />
</p:column>
</p:dataTable>
</column>
</p:dataTable>