Edit2 - I've added the faces-config.xml at the end of the post.
I'm having problems with Primefaces datatable row selection. I want to be able to select a row and move the data into an object that I can then manipulate. I'm using a model based on the primefaces showcase example, but it doesn't work. Frankly, I'm running out of ideas as to what is wrong. Below is my xhtml and managedbean.
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui" >
<h:head>
</h:head>
<h:body>
<center>
<h:form id="form">
<p:dataTable id="personTable" var="client" value="#{tableBean.persons}" rowKey="#{client.name}"
selection="#{tableBean.person}" selectionMode="single">
<f:facet name="header">
Click "View" button after selecting a row to see details
</f:facet>
<p:column headerText="Name">
#{client.name}
</p:column>
<p:column headerText="Address">
#{client.address}
</p:column>
<p:column headerText="Phone" >
#{client.phone}
</p:column>
</p:dataTable>
<h:panelGrid id="display" columns="2" cellpadding="4">
<h:outputText value="Name:" />
<h:outputText value="#{tableBean.person.name}" />
<h:outputText value="Address:" />
<h:outputText value="#{tableBean.person.address}" />
<h:outputText value="Phone:" />
<h:outputText value="#{tableBean.person.phone}" />
</h:panelGrid>
</h:form>
</center>
</h:body>
</html>
Managed Bean here:
package com.dave.test;
import java.util.ArrayList;
import java.util.List;
public class TableBean {
private List<Person> persons = null;
private Person person;
public TableBean() {
persons = new ArrayList<Person>();
persons.add(new Person("Jimmy", "18 Maple", "337-278-1019"));
persons.add(new Person("Sally", "47 Oak", "787-509-3819"));
persons.add(new Person("Roger", "754 Fifth Ave.", "926-420-8219"));
persons.add(new Person("Mimi", "891 2nd St.", "713-371-8632"));
}
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Thanks, Dave
<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="2.0" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-
facesconfig_2_0.xsd">
<managed-bean>
<managed-bean-name>tableBean</managed-bean-name>
<managed-bean-class>com.dave.test.TableBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
</faces-config>
I'm assuming that when you click the row, there is no data. That is because you are using a request scoped bean. This means that when you load the page, the bean is populated. After the page is loaded, the bean is gone.
I would suggest changing your scope to ViewScope to see if that helps at all.
Also, if you're using jsf 2.0, you can use annotations instead of the faces-config.xml file. Your backer would look like this:
package com.dave.test;
import java.util.ArrayList;
import java.util.List;
public class TableBean {
private List<Person> persons = null;
private Person person;
#ManagedBean
#ViewScoped
public TableBean() {
persons = new ArrayList<Person>();
persons.add(new Person("Jimmy", "18 Maple", "337-278-1019"));
persons.add(new Person("Sally", "47 Oak", "787-509-3819"));
persons.add(new Person("Roger", "754 Fifth Ave.", "926-420-8219"));
persons.add(new Person("Mimi", "891 2nd St.", "713-371-8632"));
}
public List<Person> getPersons() {
return persons;
}
public void setPersons(List<Person> persons) {
this.persons = persons;
}
public Person getPerson() {
return person;
}
public void setPerson(Person person) {
this.person = person;
}
}
Now you can remove your managed bean stuff from faces-config.xml.
EDIT
I just realized you don't have an ajax event to handle the row selection. If you're looking at the primefaces instant row selection, you need to notice that they are using <p:ajax event="rowSelect" ..../> along with a method in the backing bean to handle this.
lo Ășnico que debes hacer es al bean TableBean.java quitarle(borrar) el #SessionScoped y a la clase Car.java quitarle #ManagedBean(name = "car") , #SessionScoped , implements Serializable.
esta clase es una simple clase no tiene porque ser un managebean unicamente son datos.
Translated:
All you have to do is to take TableBean.java bean (delete) the #SessionScoped and take Car.java class #ManagedBean (name = "car"), #SessionScoped, implements Serializable. This class is a simple class need not be a managebean only are data.
Related
I'm trying to create a DataTables with Cell Editing with Click such as presented here : https://www.primefaces.org/showcase/ui/data/datatable/edit.xhtml
The problem I have is that the table won't take modifications into account.
I have no problem displaying the datas from the MySQL Database. The table is loaded correctly with no errors. When I try modifying a cell, it becomes an input as expected. But when I change the value and press enter, the cell goes back to it's original value. If I re-enter edit mode on that cell, my modification reappears. Not modifications are made in the Database.
I'm not very at ease with JSF and PrimeFaces and I'm surely missing something obvious.
Here is my code :
Managed Bean :
package Application;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
import org.primefaces.event.CellEditEvent;
import org.primefaces.event.RowEditEvent;
#Named(value = "plantCtrl")
#ViewScoped
public class PlantCtrl implements Serializable {
#EJB
private PlantDAO plantDAO;
public PlantCtrl() {
}
#PostConstruct
public void init(){
}
public List<Plant> getPlants() {
return plantDAO.allPlants();
}
public PlantDAO getPlantDAO() {
return plantDAO;
}
public void setPlantDAO(PlantDAO plantDAO) {
this.plantDAO = plantDAO;
}
public void onRowEdit(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Plant Edited");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowCancel(RowEditEvent event) {
FacesMessage msg = new FacesMessage("Edit Cancelled");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onCellEdit(CellEditEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if(newValue != null && !newValue.equals(oldValue)) {
FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Cell Changed", "Old: " + oldValue + ", New:" + newValue);
FacesContext.getCurrentInstance().addMessage(null, msg);
}
}
}
PlantDAO :
package Application;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
#Stateless
public class PlantDAO {
#PersistenceContext(unitName = "CarnivorousGardenPU")
private EntityManager em;
public List<Plant> allPlants() {
Query query = em.createNamedQuery("Plant.findAll");
return query.getResultList();
}
public void add(Plant p) {
em.persist(p);
em.flush();
}
public void edit(Plant p) {
em.merge(p);
em.flush();
}
public void remove(Plant p) {
em.remove(em.merge(p));
em.flush();
}
}
XHTML :
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Dashboard</title>
</h:head>
<h:body>
<ui:include src="inc/header.xhtml" />
<h:form id="plantAdminList">
<p:growl id="msgs" showDetail="true"/>
<p:dataTable id="plantsTable" var="plant" value="#{plantCtrl.plants}" editable="true" editMode="cell" widgetVar="cellPlants">
<f:facet name="header">
Cell Editing with Click and RightClick
</f:facet>
<p:ajax event="cellEdit" listener="#{plantCtrl.onCellEdit}" update=":plantAdminList:msgs, :plantAdminList:plantsTable" />
<p:column headerText="Id">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{plant.genusPlant}" /></f:facet>
<f:facet name="input"><p:inputText id="modelInput" value="#{plant.genusPlant}" style="width:96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column headerText="Price">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#{plant.pricePlant}" /></f:facet>
<f:facet name="input"><p:inputText value="#{plant.pricePlant}" style="width:96%" label="Price"/></f:facet>
</p:cellEditor>
</p:column>
</p:dataTable>
</h:form>
<ui:include src="/inc/footer.xhtml" />
</h:body>
</html>
Plant.java is generated automatically by Netbeans as an Entity Classes From Database. I'm not posting it for not overloading this post but if it is needed, don't hesitate to ask.
Modify few lines of your managed bean like this
//....
List<Plant> plants;
#PostConstruct
public void init(){
plants=plantDAO.allPlants();
}
public List<Plant> getPlants() {
return plants;
}
//....
and it will work as you want: when you change the value and press enter, the cell will reflect your changes.
Notice that:
if you want to persist changes to database you will need to modify your p:dataTable a bit and create additional logic in managed bean to detect modifications and to pass them to already existing plantDao.edit method. Minimum of coding would be:
Modify data table like this
p:dataTable id="plantsTable" var="plant" value="#{plantCtrl.plants}" editable="true" widgetVar="cellPlants">
<p:ajax event="rowEdit" listener="#{plantCtrl.onRowEdit}"
update=":plantAdminList:msgs, :plantAdminList:plantsTable" />
....
<p:column style="width:32px">
<p:rowEditor />
</p:column>
</p:dataTable>
Modify onEditMethod inside managed bean
public void onRowEdit(RowEditEvent event) {
Plant editedPlant = (Plant)event.getObject();
plantDAO.edit(plant);
FacesMessage msg = new FacesMessage("Plant Edited");
FacesContext.getCurrentInstance().addMessage(null, msg);
}
I have two dropdowns: One is implemented using a selectOneMenu component and the other is implemented with selectCheckboxMenu.
When selecting an option in the selectOneMenu, the option values of the selectCheckboxMenu are updated depending of what option was selected in the selectOneMenu.
The following scenario happens:
I select an option of the selectOneMenu, the selectCheckboxMenu gets populated
I select/check some options of the selectCheckboxMenu
I select another option of the selectOneMenu, the selectCheckboxMenu gets populated with other values
I select some of the new values
I select the option in step 1 of the selectOneMenu
The values I selected in step 2 are no longer selected
I believe this is because the list value bound to the selectCheckboxMenu is getting reset by the setter method.
What I would like is for the state of the selectCheckboxMenu to be globally saved. What would be the best strategy for doing this?
EDIT:
Here's the relevant code that duplicates the previous behavior:
Bean:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
#ManagedBean
#ViewScoped
public class BackingBean {
private List<Parent> parents = new ArrayList<>();
private List<Child> children = new ArrayList<>();
private List<Child> selectedChildren = new ArrayList<>();
private Parent selectedParent = new Parent();
#Inject
FamilyService service;
#PostConstruct
public void init(){
parents = service.findParents();
}
public void parentChanged(){
children = new ArrayList<>();
if(getSelectedParent() == null){
return;
}
children = service.findChildrenByParent(getSelectedParent());
}
public void selectedSonChanged(){
System.out.println(selectedChildren.size());
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public List<Child> getSelectedChildren() {
return selectedChildren;
}
public void setSelectedChildren(List<Child> selectedChildren) {
this.selectedChildren = selectedChildren;
}
public Parent getSelectedParent() {
return selectedParent;
}
public void setSelectedParent(Parent selectedParent) {
this.selectedParent = selectedParent;
}
}
XHTML:
<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.org/ui">
<h:head></h:head>
<h:body>
<h:form id="selectOne">
<p:messages autoUpdate="true" />
<h:outputLabel for="parents" value="Parents:" />
<p:selectOneMenu converter="#{parentConverter}" id="parents" value="#{backingBean.selectedParent}">
<p:ajax update="children" listener="#{backingBean.parentChanged}" />
<f:selectItem noSelectionOption="true" value="#{null}" itemLabel="None" />
<f:selectItems value="#{backingBean.parents}" var="p" itemLabel="#{p.name}" itemValue="#{p}" />
</p:selectOneMenu>
<h:outputLabel for="children" value="Children:" />
<p:selectCheckboxMenu converter="#{childConverter}" id="children"
value="#{backingBean.selectedChildren}"
label="Children" filter="true" filterMatchMode="startsWith">
<p:ajax update="display" listener="#{backingBean.selectedSonChanged}" />
<f:selectItems value="#{backingBean.children}" var="c" itemLabel="#{c.name}" itemValue="#{c}" />
</p:selectCheckboxMenu>
<p:outputPanel id="display">
<p:dataList value="#{backingBean.selectedChildren}" var="sn" emptyMessage="No children selected">
#{sn.name}
</p:dataList>
</p:outputPanel>
<p:commandButton value="Submit" update="display, selectOne" />
</h:form>
</h:body>
</html>
The complete project is here: https://github.com/cenobyte321/jsfsamples/tree/master/selectcheckboxmenu
You can find a video of the interaction mentioned previously here:
https://github.com/cenobyte321/jsfsamples/blob/master/selectcheckboxmenu/example1.mp4?raw=true
As you can see when choosing another "Parent" and then selecting their children the previous children list gets substituted. How can I properly modify this behavior so the previously selected elements get persisted and shown as checked in the selectCheckboxMenu?
EDIT 2:
One solution I found was introducing another variable which will hold the global values and will be modified in the listener method "selectedSonChanged". Here's the relevant code:
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
#ManagedBean
#ViewScoped
public class BackingBean {
private List<Parent> parents = new ArrayList<>();
private List<Child> children = new ArrayList<>();
private List<Child> selectedChildren = new ArrayList<>();
private List<Child> globalSelectedChildren = new ArrayList<>();
private Parent selectedParent = new Parent();
#Inject
FamilyService service;
#PostConstruct
public void init(){
parents = service.findParents();
}
public void parentChanged(){
children = new ArrayList<>();
if(getSelectedParent() == null){
return;
}
children = service.findChildrenByParent(getSelectedParent());
selectedChildren = globalSelectedChildren.stream().filter(c -> c.getParent().equals(selectedParent)).collect(Collectors.toList());
System.out.println(selectedChildren.size());
}
public void selectedSonChanged(){
System.out.println(selectedChildren.size());
globalSelectedChildren = globalSelectedChildren.stream().filter(c -> !c.getParent().equals(selectedParent)).collect(Collectors.toList());
globalSelectedChildren.addAll(selectedChildren);
}
public List<Parent> getParents() {
return parents;
}
public void setParents(List<Parent> parents) {
this.parents = parents;
}
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public List<Child> getSelectedChildren() {
return selectedChildren;
}
public void setSelectedChildren(List<Child> selectedChildren) {
this.selectedChildren = selectedChildren;
}
public Parent getSelectedParent() {
return selectedParent;
}
public void setSelectedParent(Parent selectedParent) {
this.selectedParent = selectedParent;
}
public List<Child> getGlobalSelectedChildren() {
return globalSelectedChildren;
}
public void setGlobalSelectedChildren(List<Child> globalSelectedChildren) {
this.globalSelectedChildren = globalSelectedChildren;
}
}
XHTML:
<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.org/ui">
<h:head></h:head>
<h:body>
<h:form id="selectOne">
<p:messages autoUpdate="true" />
<h:outputLabel for="parents" value="Parents:" />
<p:selectOneMenu converter="#{parentConverter}" id="parents" value="#{backingBean.selectedParent}">
<p:ajax update="children" listener="#{backingBean.parentChanged}" />
<f:selectItem noSelectionOption="true" value="#{null}" itemLabel="None" />
<f:selectItems value="#{backingBean.parents}" var="p" itemLabel="#{p.name}" itemValue="#{p}" />
</p:selectOneMenu>
<h:outputLabel for="children" value="Children:" />
<p:selectCheckboxMenu converter="#{childConverter}" id="children"
value="#{backingBean.selectedChildren}"
label="Children" filter="true" filterMatchMode="startsWith">
<p:ajax update="display" listener="#{backingBean.selectedSonChanged}" />
<f:selectItems value="#{backingBean.children}" var="c" itemLabel="#{c.name}" itemValue="#{c}" />
</p:selectCheckboxMenu>
<p:outputPanel id="display">
<p:dataList value="#{backingBean.globalSelectedChildren}" var="sn" emptyMessage="No children selected">
#{sn.name}
</p:dataList>
</p:outputPanel>
<p:commandButton value="Submit" update="display, selectOne" />
</h:form>
</h:body>
</html>
Here's the branch with this solution: https://github.com/cenobyte321/jsfsamples/tree/solution-1/selectcheckboxmenu
I have a set of p:accordionPanel's that I wish to update in my JSF 2.2 page.
The first one lists items of the list as tabs, in the tab it shows the name of the list item plus a button to delete that item. Clicking delete correctly removes the item and updates the panel via ajax
When all items have been removed it will render a new accordion panel informing the user there are no items and one needs to be added.
This all works fine, however when a new item is added is should once again render the first accordion panel showing the item with the option to remove it.
I believe the following is Minimal, Complete and Verifiable (if not please let me know why not)
The xHTML
<!DOCTYPE html>
<html xmlns="http://www.w3c.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Forms</title>
</h:head>
<h:body>
<h:form id="mainForm">
<p:outputPanel id="panelContainer">
<p:accordionPanel id="formsPanel" value="#{formController.forms}"
var="formInstance" rendered="#{not empty formController.forms}">
<p:tab title="#{formInstance.name}">
<p:panelGrid columns="3" layout="grid">
<h:outputLabel for="name" value="Form name:" />
<h:outputText id="name" value="#{formInstance.name}" />
<p:commandButton
action="#{formController.deleteForm(formInstance.name)}"
value="Delete form" update=":mainForm:panelContainer" />
</p:panelGrid>
</p:tab>
</p:accordionPanel>
<p:accordionPanel id="addFormPanel"
rendered="#{empty formController.forms}">
<p:tab title="No forms added yet, please add some">
<h:form>
<p:panelGrid columns="3" layout="grid">
<h:outputLabel value="Form name:" />
<p:inputText value="#{formController.form.name}" required="true"
label="text" />
<p:commandButton update=":mainForm:panelContainer"
action="#{formController.createForm}" value="Add form" />
</p:panelGrid>
</h:form>
</p:tab>
</p:accordionPanel>
</p:outputPanel>
</h:form>
</h:body>
</html>
The Form
public class Form implements Serializable
{
private String name;
public Form()
{
}
public Form(String name)
{
this.name = name;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
}
And the FormController
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
#Named
#ViewScoped
public class FormController implements Serializable
{
private static List<Form> forms;
{
forms = new ArrayList<>();
forms.add(new Form("Form 1"));
forms.add(new Form("Form 2"));
}
private Form form = new Form();
public void createForm()
{
forms.add(form);
form = new Form();
}
public void deleteForm(String name)
{
for(int i=0; i < forms.size(); i++)
{
Form form = forms.get(i);
if (form.getName().equals(name))
{
forms.remove(i);
}
}
}
public List<Form> getForms()
{
return forms;
}
public Form getForm()
{
return form;
}
}
If I run the app and click the first p:commandLink, the item gets set as expected. When clicking another p:commandLink the previous one will be removed (null). The h:commandLink does not have that problem.
If I add :theform:output to the update parameter of the p:commandLink, the previously clicked item stops disappearing.
What is the reason for this behaviour?
Env
Java 1.7.45
Netbeans 7.4
JSF Mojarra 2.2.4
Primefaces 4.0
Index.xhtml
<?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:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<h:form id="theform">
<h:panelGroup layout="block" styleClass="tableBorder" id="tableWrapper">
<h:dataTable value="#{xtestListBean.list}" var="item">
<h:column>
<h:outputText value="#" styleClass="tableItem" />
</h:column>
<h:column>
<h:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}">
<f:ajax render=":theform:tableWrapper" />
</h:commandLink>
<p:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}"
update=":theform:tableWrapper">
</p:commandLink>
</h:column>
</h:dataTable>
</h:panelGroup>
<h:inputText value="#{xtestEntityBean.item.name}" size="40" id="output" />
</h:form>
</h:body>
</html>
XtestListBean.java
package beans;
import dto.Item;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class XtestListBean implements Serializable {
private List<Item> list;
public XtestListBean() {
list = new ArrayList();
list.add(new Item("Test 1"));
list.add(new Item("Test 2"));
list.add(new Item("Test 3"));
list.add(new Item("Test 4"));
list.add(new Item("Test 5"));
list.add(new Item("Test 6"));
list.add(new Item("Test 7"));
}
public List<Item> getList() {
return list;
}
}
XtestEntityBean.java
package beans;
import dto.Item;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
#ManagedBean
#ViewScoped
public class XtestEntityBean implements Serializable {
private Item item = new Item();
public XtestEntityBean() {
}
public void setItem(Item item) {
this.item = item;
}
public Item getItem() {
return item;
}
public String getVersion() {
return FacesContext.class.getPackage().getImplementationTitle()
+ " version "
+ FacesContext.class.getPackage().getImplementationVersion();
}
}
That only looks like so. It's just that the <h:inputText value="#{xtestEntityBean.item.name}"> is also processed when the <p:commandLink> is invoked. In effects, the item's name is submitted with an empty/null value and that get reflected in the table. It's not the whole Item instance which became null or so.
How is this caused? Well, the <f:ajax execute> defaults to #this, meaning that only the current component (i.e. the command link) is processed during the form submit. However, the PrimeFaces equivalent, <p:commandLink process> defaults to #form, meaning that the entire parent form is processed during form submit, including that empty input field referring the item name.
If you explicitly set <p:commandLink process> to #this, the same as <f:ajax execute>'s default, then it should work as intented.
<p:commandLink
value="#{item.name}"
actionListener="#{xtestEntityBean.setItem(item)}"
process="#this" update=":theform:tableWrapper">
</p:commandLink>
I am following the example given here. I have to show CheckBox and RadioButton for a list of Employees, where user can select many CheckBoxs, but only one RadioButton. Just the normal behaviour. I started with Radiobutton first and after running all my radiobuttons are selected automatically.
I have the below index.xhtml page
<!DOCTYPE html>
<html lang="en"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:event listener="#{userPreferenceBean.preRender}" type="preRenderView" />
<h:head>
<title>Datatable with Checkbox and RadioButton Example</title>
</h:head>
<h:body>
<h:form>
<p:dataTable id="employeeDataTable" var="employee" value="#{userPreferenceBean.employeeList}"
rowKey="#{userPreferenceBean.employeeDataModel}" paginator="true" rows="10"
selection="#{userPreferenceBean.selectedEmployeeList}">
<f:facet name="header">
Showing employee List
</f:facet>
<p:column selectionMode="single" style="width:2%"></p:column>
<p:column headerText="Name" style="width:48%">
#{employee.name}
</p:column>
<p:column headerText="Department" style="width:48%">
#{employee.department}
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
My Backing bean is:
#ManagedBean
#SessionScoped
public class UserPreferenceBean implements Serializable{
private static final long serialVersionUID = 1L;
private List<Employee> employeeList;
private List<Employee> selectedEmployeeList;
private EmployeeDataModel employeeDataModel;
public void preRender(ComponentSystemEvent ebent){
System.out.println("Inside prerender");
}
#PostConstruct
public void initializeEmployeeList(){
createEmployeeList();
employeeDataModel = new EmployeeDataModel(employeeList);
}
private void createEmployeeList(){
employeeList = new ArrayList<>();
employeeList.add(new Employee("Sudipta",29,"Computer"));
employeeList.add(new Employee("Bunty", 29, "Electrical"));
employeeList.add(new Employee("Pradipta", 24, "Computer"));
}
//Other Getter and Setters
Below is the POJO Class of Employee:
public class Employee implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
private String department;
//Constructor and Getters+Setters
And this is my DataModel class:
public class EmployeeDataModel extends ListDataModel<Employee> implements SelectableDataModel<Employee>{
public EmployeeDataModel(){
}
public EmployeeDataModel(List<Employee> employees){
super(employees);
}
#Override
public Employee getRowData(String rowKey) {
#SuppressWarnings("unchecked")
List<Employee> employees = (List<Employee>) getWrappedData();
for(Employee employee : employees){
if(employee.getName().equals(rowKey))
return employee;
}
return null;
}
#Override
public Object getRowKey(Employee employee) {
return employee.getName();
}
}
Do you have any idea why all radiobuttons are getting selected automatically and what changes I need to do? Thanks. Attached is the screenshot
You are not using the employeeDataModel properly, your value attribute of the table should be init in the following way
value="#{userPreferenceBean.employeeDataModel}"
and I think you can remove the rowKey attribute
Take a look at the following example DataTable - Instant Row Selection
I don't think it's possible to have a list of radiobuttons where only 1 can be selected and then 1 checkbox to select all the radiobuttons. Normal behavior with radiobuttons is that only 1 can be selected. If you only use checkboxes this is possible, but even then only the displaying page will be selected. You can test this in the showcase.
If I were you I would implement the solution with only the checkboxes.
Finally I am able to solve the problem. The problem was below:
Since my selectionMode was single like
<p:column selectionMode="single" style="width:2%"></p:column>
so I need selection="#{userPreferenceBean.selectedEmployee}" rather than the list of employees.
Now the index.xhtml looks like:
<p:dataTable id="employeeDataTable" var="employee" value="#{userPreferenceBean.employeeDataModel}"
paginator="true" rows="10" selection="#{userPreferenceBean.selectedEmployee}">
<f:facet name="header">
Showing employee List
</f:facet>
<p:column selectionMode="single" style="width:2%" />
<p:column headerText="Name" style="width:48%">
#{employee.name}
</p:column>
<p:column headerText="Department" style="width:48%">
#{employee.department}
</p:column>
</p:dataTable>
And I added the below member in my backing bean.
private Employee selectedEmployee; with getters and setters. Now it is working fine.
Full code is # myGitHubRepo
Thanks.