I have a web app that uses dataTables in JSF and Primefaces features so that it may perform some more dynamic functions. In the dataTable I have rows that contain editable data. My ultimate goal is to have users be able to edit that data, click a save button, and update statements will be executed to replace what's present in the database. The problem is that at this time I do not know how to detect changes in objects within an arrayList.
I have made an example to see if anyone can solve my dilemma. Hear I have code that makes a dataTable and in the dataTable are objects from an ArrayList, each object containg three different strings. The objects are editable in the datatable. I need to be able to at minimum retrieve the ArrayList index of the object that is edited on the page. With that, I could form a new list of edited objects, and write up a method that executes a batch update on only the objects edited (an object in my scenario is equivalent to a row of data in the database) . My previous method was iterating through the entire ArrayList and updating all objects (rows), but, as the list grows large, this becomes very expensive to do. Right now I have a primefaces method onCellEdit, which tells me a previous value and the value it was changed to, but no way of pinpointing the object changed. Any help would be appreciated. The code below is set up so that it may be copied and pasted and executed.
Edit:
In my situation, I do not need to update the ArrayList. That is done automatically using the inputs on the pages and the getter and setters for the bean. What I need to do is know which objects (rows) are edited so that I may pull them aside and perform a database update, where i only update what is edited. The ArrayList is a mirror of what is in the database, but the goal here is to update the database to mirror the edited ArrayList, without having to iterate through the entire List.
Prod.java
public class Prod{
private String value1;
private String value2;
private String value3;
public String getValue1() {
return value1;
}
public void setValue1(String value1) {
this.value1 = value1;
}
public String getValue2() {
return value2;
}
public void setValue2(String value2) {
this.value2 = value2;
}
public String getValue3() {
return value3;
}
public void setValue3(String value3) {
this.value3 = value3;
}
}
Listen.java
import java.io.IOException;
import java.util.ArrayList;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import org.primefaces.event.CellEditEvent;
import com.product.inventory.beans.Prod;
#ManagedBean(name = "listen")
#SessionScoped
public class Listen{
private ArrayList<Prod> products;
boolean firstEdit = true;
public Listen(){
}
public ArrayList<Prod> setup(){
ArrayList<Prod> result = new ArrayList<>();
int numObject = 100;
int iterations = 0;
while( iterations < numObject){
Prod prod = new Prod();
prod.setValue1("A" + iterations);
prod.setValue2("B" + iterations);
prod.setValue3("C" + iterations);
result.add(prod);
iterations = iterations + 1;
}
return result;
}
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);
}
if(isFirstEdit()){
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new
FacesMessage(FacesMessage.SEVERITY_INFO,
"Note", "To confirm changes, please select 'Save Changes'
or they will not be saved.") );
this.setFirstEdit(false);
}
}
public void goTest(){
System.out.println("Initializing...");
this.products = setup();
ExternalContext ec = FacesContext.getCurrentInstance()
.getExternalContext();
try {
ec.redirect(ec.getRequestContextPath()
+ "/test.xhtml");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Table Structure Made");
}
public boolean isFirstEdit() {
return firstEdit;
}
public void setFirstEdit(boolean firstEdit) {
this.firstEdit = firstEdit;
}
public ArrayList<Prod> getProducts() {
return products;
}
public void setProducts(ArrayList<Prod> products) {
this.products = products;
}
}
test.xhtml
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form id="form" method="post">
<p:growl id="msgs" showDetail="true" sticky="false">
</p:growl>
<div >
<p:dataTable id="products" var="prod" value="#{listen.products}"
scrollable="true" scrollHeight="900"
editable = "true" editMode="cell" widgetVar= "prodCell">
<p:ajax event="cellEdit" listener="#{listen.onCellEdit}"
update=":form:msgs"/>
<p:column filterBy="#{prod.value1}" filterMatchMode="contains"
style = "width: 300px;" headerText="Name">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#
{prod.value1}" /></f:facet>
<f:facet name="input"><p:inputTextarea rows="2" value="#
{prod.value1}" style = "width: 96%"/></f:facet>
</p:cellEditor>
</p:column>
<p:column style = "width: 140px;" headerText="Vendor">
<p:cellEditor >
<f:facet name="output"><h:outputText value="#
{prod.value2}" /></f:facet>
<f:facet name="input">
<h:selectOneMenu value="#{prod.value2}"
style="width:100%">
<f:selectItem itemValue="Y" itemLabel="Yes"/>
<f:selectItem itemValue="N" itemLabel="No"/>
</h:selectOneMenu>
</f:facet>
</p:cellEditor>
</p:column>
<p:column style = "width: 275px;" headerText="Version Release">
<p:cellEditor>
<f:facet name="output"><h:outputText value="#
{prod.value3}" /></f:facet>
<f:facet name="input"><p:inputTextarea rows="1" value="#
{prod.value3}" style = "width: 96%"/></f:facet>
</p:cellEditor>
</p:column>
<f:facet name="footer">
<div align = "left">
<p:commandButton value="post" action="#{tables.showChange}"
ajax="false"></p:commandButton>
</div>
</f:facet>
</p:dataTable>
</div>
<p:contextMenu for="products" widgetVar="pMenu">
<p:menuitem value="Edit Cell" icon="pi pi-search"
onclick="PF('prodCell').showCellEditor();return false;"/>
<p:menuitem value="Hide Menu" icon="pi pi-times"
onclick="PF('pMenu').hide()"/>
</p:contextMenu>
</h:form>
Index.xhtml
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<h:form method="post">
<h:commandButton value = "Contact Spreadsheet" ajax="false"
action="#{listen.goTest}" ></h:commandButton>
</h:form>
</h:body>
</html>
The solution you want is the PrimeFaces Extensions Sheet component for the behavior you are looking for.
Sheet fills a need that the PrimeFaces Datatable with in-cell editing does not fill. It can handle a large amount of data with editing single cells without submitting the entire sheet. Provides familiar spreadsheet navigation with TAB and SHIFT+TAB and familiar spreadsheet experience.
Features include:
Fast In-Cell Editing and Validation
Copy/Paste Range Selection including Copy/Paste and Fill
Sorting
Filtering
Fixed Columns and Rows
Resizable Columns and Rows
Movable Columns and Rows
Ajax Updates and Validation
Based on Handsontable by Handsoncode.
Related
first of all, I am writing this because I am desperate. The thing is I was doing a simple Spring Boot CRUD with Primefaces. I used a bean called "carBean" to access the data in the index.xhtml file. Until there everything ok, things started to turn weird from now on. I tried to use a simple inputText to bind a text given in the UI to a property in the bean.
But I was constantly getting error 500, telling me that the property "marca" was not found in the bean, and I have checked 10000 times and everything is OK in there. So I started testing, and eventually I figured out that, the property that was working fine "carBean.cars" if I change the name to whatever I change (and obviously the methods liked to the property), It stop working. Is like the only property that works has to be named "cars". What I am missing here? Is driving me crazy, I promise this was my last resource. Thanks in advance .
carBean
package com.example.bean;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import com.example.controller.CarController;
import com.example.dto.CarDTO;
import lombok.Data;
#Data
#Named("carBean")
#Scope(value = "session")
public class CarBean implements Serializable {
private static final long serialVersionUID = -8338541378806874723L;
#Autowired
CarController carController;
private List<CarDTO> cars;
private Integer id;
private String marca;
private String modelo;
private String precio;
private String bastidor;
private String potencia;
public String getMarca() {
return marca;
}
public void setMarca(String marca) {
this.marca = marca;
}
public List<CarDTO> getCars() {
cars = carController.getAllCars();
return cars;
}
public void delete(CarDTO car) {
carController.deleteCar(car.id);
cars = carController.getAllCars();
}
public void add() {
CarDTO newCar = new CarDTO();
newCar.marca = this.marca;
newCar.modelo = this.modelo;
newCar.precio = this.precio;
newCar.bastidor = this.bastidor;
newCar.potencia = this.potencia;
carController.create(newCar);
}
public String redirect() {
return "index.xhtml?faces-redirect=true";
}
}
index.xhtml
<!DOCTYPE xhtml 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:rich="http://richfaces.org/rich"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<h3> REGISTRO DE COCHES </h3>
<h:form id = "tabla">
<div class="card">
<p:dataTable var="car" value="#{carBean.cars}">
<p:column sortBy="#{car.marca}" headerText="Marca">
<h:outputText value="#{car.marca}" />
</p:column>
<p:column sortBy="#{car.modelo}" headerText="Modelo">
<h:outputText value="#{car.modelo}" />
</p:column>
<p:column sortBy="#{car.precio}" headerText="Precio">
<h:outputText value="#{car.precio}" />
</p:column>
<p:column sortBy="#{car.bastidor}" headerText="Bastidor">
<h:outputText value="#{car.bastidor}" />
</p:column>
<p:column sortBy="#{car.potencia}" headerText="Potencia">
<h:outputText value="#{car.potencia}" />
</p:column>
<p:column>
<p:commandButton type="submit" value="Eliminar" actionListener="#{carBean.delete(car)}"
update=":tabla" />
<p:commandButton type="button" value="Editar"/>
</p:column>
</p:dataTable>
<p:commandButton value="Nuevo Coche" type="submit" oncomplete="PF('createModal').show();"/>
</div>
</h:form>
<p:dialog header="Agregar" widgetVar="createModal" id="createModal">
<h:form id="createDialog">
<p:panel header="Detalles del coche">
<h:panelGrid columns="1">
<h:outputLabel value="Marca:"/>
<h:inputText id="marca" value="#{carBean.marca}" required="true"> </h:inputText>
<h:outputLabel value="Modelo"/>
<h:inputText id="modelo"> </h:inputText>
<h:outputLabel value="Precio"/>
<h:inputText id="precio"> </h:inputText>
<h:outputLabel value="Bastidor"/>
<h:inputText id="bastidor"> </h:inputText>
<h:outputLabel value="Potencia"/>
<h:inputText id="potencia"> </h:inputText>
</h:panelGrid>
</p:panel>
</h:form>
</p:dialog>
</h:head>
</html>
Why I cannot used other property that isnĀ“t called "cars"?
Don't mess Lombok #Data autogenerated getters and setters with the one you've declared in the Bean.
You have used a getter as a method, which is not a good thing to do because it can be called multiple times, see: Why JSF calls getters multiple times
public List<CarDTO> getCars() {
cars = carController.getAllCars(); // remove business logic from getter
return cars;
}
Better initialize your private List<CarDTO> cars variable in a method annotated with #PostContruct
#PostConstruct
public void init() {
cars = carController.getAllCars();
}
For more check this example: PrimeFaces DataTable CRUD
I have a datatable on jsf page with next columns: product name, price and input field for product amount. By click on the button I should load elements from datatable to collection where product amount is more than 0(method addCups).
How to create it?
Thank you.
Managed Bean
#ManagedBean
#SessionScoped
public class OrderBean extends SpringBeanAutowiringSupport {
#Autowired
private OrderDAO orderDAO;
#Autowired
private OrderPositionDAO orderPositionDAO;
private Map<Long, Integer> selectedItems = new HashMap<>();
private Integer quantityOfCups;
public Map<Long, Integer> getSelectedItems() {
return selectedItems;
}
public void setSelectedItems(Map<Long, Integer> selectedItems) {
this.selectedItems = selectedItems;
}
public Integer getQuantityOfCups() {
return quantityOfCups;
}
public void setQuantityOfCups(Integer quantityOfCups) {
this.quantityOfCups = quantityOfCups;
}
public void addCups(Long id, Integer numOfCups){
if(numOfCups > 0){
selectedItems.put(id, numOfCups);
}
if(numOfCups == 0){
selectedItems.remove(id);
}
System.out.println(selectedItems);
}
JSF page
<?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:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:p="http://primefaces.org/ui">
<h:form>
<p:dataTable value="#{coffeeBean.allCoffee}" var="coffee">
<p:column>
<h:outputText value="#{coffee.coffeeName}"/>
</p:column>
<p:column>
<h:outputText value="#{coffee.costForCup}"/>
</p:column>
<p:column>
<p:inputText value="#{orderBean.quantityOfCups}"/>
</p:column>
</p:dataTable>
<h:commandButton value="add cups" action="#{orderBean.addCups(coffee.id, orderBean.quantityOfCups)}"/>
</h:form>
There are number of ways to achieve this but, with minimal modifications of your posted code, you can achieve it on following way:
add one hidden data table column with your coffee ID and define widgetVar property of data table ,
use JavaScript method to iterate through data table values and pick up coffee ID-quantity pairs,
use p:remoteCommand to send array of coffee cups as JSON string to backing bean
inside bean method parse passed JSON string and add/remove coffee cups to/from your order
Your xhtml page h:form would look like this
<h:form>
<p:dataTable widgetVar="dataTableWidget" value="#{coffeeBean.allCoffee}" var="cofee">
<p:column style="display:none">
<h:outputText value="#{coffee.id}"/>
</p:column>
<p:column headerText="name">
<h:outputText value="#{coffee.coffeeName}"/>
</p:column>
<p:column headerText="price">
<h:outputText value="#{coffee.costForCup}"/>
</p:column>
<p:column headerText="quantity">
<p:inputText/>
</p:column>
</p:dataTable>
<p:commandButton value="Add cups" type="button" onclick="collectOrderFromTable()"/>
<p:remoteCommand name="sendToOrderBean" actionListener="#{orderBean.addCups}"/>
</h:form>
with added java script
<script>
//<![CDATA[
function collectOrderFromTable() {
var coffeeCups = [];
//get table rows
var tableRows = PF('dataTableWidget').tbody[0].childNodes;
//loop through rows
for (i = 0; i < tableRows.length; i++) {
//get cells of current row
var cells = tableRows[i].cells;
//get value of hidden ID column
var id = cells[0].innerText;
//get quantity from input field
var quantity = cells[3].firstChild.value;
//add new item to array
coffeeCups.push({id: id, quantity: quantity});
}
console.log("Coffee cups", JSON.stringify(coffeeCups));
sendToOrderBean([{name: 'coffeeCups', value: JSON.stringify(coffeeCups)}]);
}
//]]>
</script>
Method addCups in your OrderBean would be like this:
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
//...
//...
public void addCups() {
//get string passed from xhtml page
String values = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("coffeCups");
//parse JSON string to List
List<CoffeeQuantity> coffeCups = (ArrayList<CoffeeQuantity>) new Gson().fromJson(values, new TypeToken<ArrayList<CoffeeQuantity>>() {}.getType());
for (CoffeeQuantity cq : coffeCups) {
System.out.println("Coffee id: " + cq.getId() + ", Quantity:" + cq.getQuantity());
if (cq.getQuantity()>0){
selectedItems.put(cq.getId(), cq.getQuantity());
}else{
selectedItems.remove(cq.getId());
}
}
}
where CoffeeQuantity is helper class to make JSON string parsing easier
public class CoffeQuantity {
int id;
Integer quantity;
//getters and setters...
}
The following is my code snippet in my abc.xhtml page :
<p:panelGrid id="pnlGrd_numOfLbl"
style="align:center; width:100%;" cellpadding="5">
<c:forEach var="i" begin="1" end="${specificationMB.numOfLbl}" >
<p:row>
<p:column width="50%">
<p:outputLabel value="Label ${i}" />
</p:column>
<p:column width="50%">
<p:inputText id="inputTxt_${i}" style="width:150px;" />
</p:column>
</p:row>
</c:forEach>
</panelGrid>
This is my panelGrid I am generating inputText dynamically depending
numOfLable. After generation say 2 will be generate user will add some
text to each inputText so my Question is How can I get value of dyanamically
generated inputbox.
Thanks.
This can easily be done with basics of JSF and primefaces. Here is full working Example:
XHTML File (I am using p:panel and ui:repeater)
<!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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view contentType="text/html">
<h:head>
<link rel=" stylesheet" type="text/css" href="css/style.css"></link>
</h:head>
<h:body>
<h:form>
<p:panel header="Panel">
<ui:repeat var="lbl" value="#{tBean.lblClassess}">
<p:row>
<p:column width="50%">
<p:outputLabel value="#{lbl.lbl} :" />
</p:column>
<p:column width="50%">
<p:inputText value="#{lbl.value}" />
</p:column>
</p:row>
</ui:repeat>
</p:panel>
<p:commandButton actionListener="#{tBean.submit}" value="Subtmi" update="values"></p:commandButton>
<p:outputPanel id="values">
<ui:repeat var="lbl" value="#{tBean.lblClassess}">
<p:row>
<p:column width="50%">
<p:outputLabel value="#{lbl.value} :" />
</p:column>
</p:row>
</ui:repeat>
</p:outputPanel>
</h:form>
</h:body>
</f:view>
<body>
</body>
</html>
Managed Bean
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
#ManagedBean(name = "tBean")
#ViewScoped
public class TestBean {
private List<LabelClass> lblClassess;
public TestBean() {
lblClassess = new ArrayList<LabelClass>();
lblClassess.add(new LabelClass("First Label", ""));
lblClassess.add(new LabelClass("Second Label", ""));
lblClassess.add(new LabelClass("Third Label", ""));
}
public void submit(ActionEvent e) {
for (LabelClass lbl : lblClassess) {
System.out.println(lbl.getValue());
}
}
public List<LabelClass> getLblClassess() {
return lblClassess;
}
public void setLblClassess(List<LabelClass> lblClassess) {
this.lblClassess = lblClassess;
}
}
Label Class
public class LabelClass {
private String lbl;
private String value;
public LabelClass(String lbl, String value) {
super();
this.lbl = lbl;
this.value = value;
}
public String getLbl() {
return lbl;
}
public void setLbl(String lbl) {
this.lbl = lbl;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
Output
In order to get the values of your dynamically generated inputTexts. You may do something like this.
<input type="text" id="inputTxt_${i}" name="inputTxt_${i}" style="width:150px;" />
Then retrieve the text value by using this code in servlet
String inputText1 = request.getParameter("nameOfFirstInputText");
You can bind the value into the bean value object:
<input type="text" id="inputTxt_${i}" value="${specificationMB.getValue(i).value}" />
I'm trying to get some code working in an XHTML/JSF/Spring application through which I send an ID to a bean function and expect a string in return. I haven't found an understandable tutorial on this nor any answered question here on SO.
XHTML:
<h:form>
<h:inputText id="inputId" value="#{npBean.idString}"/>
<a4j:commandButton value="get def" render="out">
<f:param value="#{npBean.idString}" name="id" />
<f:setPropertyActionListener target="#{npBean.definition}"/>
</a4j:commandButton>
<a4j:outputPanel id="out">
<h:outputText id="outputId" value="#{npBean.def}"
rendered="#{not empty npBean.def}"/>
</a4j:outputPanel>
</h:form>
Java:
public String getDefinition(int id)
{
def = this.getXService().getXData(id).getDefinition();
return def;
}
All values shown have their getters and setters in the bean.
What we basically do:
Map the value of the <h:inputText> component to a property (with getter/setter) in the managed-bean (which is called myBean)
By using the reRender attribute of the <a4j:commandButton> component, we point which component on the page to be re-rendered (refreshed) when the button is clicked.
When clicking on the button, the invokeService() method from the managedBean is executed and it updates the other property of the managedBean.
In the <h:panelGroup> below, we have several <h:outputText> components and with the rendered attribute we specify when a component has to be displayed on the page.
Exploring the managed-bean, the only thing that is required, are the accessors for the property, which holds the result from the service invoke.
Here's the *.xhtml sample:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">
<a4j:form>
<h:panelGrid columns="3">
<h:outputText value="String value:" />
<h:inputText value="#{myBean.value}" />
<a4j:commandButton value="Click" reRender="out">
<a4j:actionListener listener="#{myBean.invokeService}" />
</a4j:comandButton>
</h:panelGrid>
</a4j:form>
<rich:spacer height="7"/>
<br />
<h:panelGroup id="out">
<h:outputText value="Service returned: " rendered="#{not empty myBean.result}" />
<h:outputText value="#{myBean.result}" />
</h:panelGroup>
</ui:composition>
Managed-bean:
#ManagedBean(name = "myBean")
#SessionScoped //for example
public class MyBean {
private String value;
private String result;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getResult() {
return result;
}
public void invokeService(ActionEvent actionEvent) {
this.result = "Hello, " + value + "!";
}
}
As #Luiggi mentioned, the accessor methods MUST meet the following conventions (if we assume you have a private <some-type> property; in the managed-bean.)
public <some-type> getProperty {
return property;
}
public void setProperty(<some-type> property) {
this.property = property:
}
In order to learn how the RichFaces components work, combined with good code examples, I suggest you open this address and play around with the components.
I have a datatable with each row having Edit and Delete buttons.
It is almost similar to http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionByColumn.jsf datatable.
When I click on Edit button, if I display the selected row values using <h:outputText> the values are being displayed properly.
But If I want to display it in a input text field using <h:inputText value="#{userCRUDMB.selectedUser.userName}"/> it is throwing error saying selectedUser is resolved as null.
If I only use <h:outputText ...> then userCRUDMB.selectedUser() method is getting called properly.
But If I use <h:inputText ...> in the Dialog, the setter method is not at all getting called.
I am using Mojarra 2.1.6, PrimeFaces 3.0, Apache Tomcat7.0.32.
Any idea why it is happening?
Code: Code is same as http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionByColumn.jsf, except in the dialogue box instead of displaying the text using I am trying to display in input textbox using .
public class User
{
private Integer userId;
private String userName;
private String password;
private String firstname;
private String lastname;
private String email;
private Date dob;
private String gender;
//setters/getters
}
package com.sivalabs.primefacesdemo.managedbeans;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import com.sivalabs.primefacesdemo.model.User;
import com.sivalabs.primefacesdemo.model.UserDataModel;
import com.sivalabs.primefacesdemo.service.SpringContainer;
import com.sivalabs.primefacesdemo.service.UserService;
#ManagedBean(name="UserCRUDMB")
#RequestScoped
public class UserCRUDMB
{
private UserDataModel userDataModel;
private User selectedUser;
private User[] selectedUsers;
public UserCRUDMB()
{
List<User> users = new ArrayList<User>();
for (int i = 0; i < 15; i++) {
User user = new User();
user.setUserId(i);
user.setUserName("userName"+i);
users.add(user);
}
this.userDataModel = new UserDataModel(users);
}
public UserDataModel getUserDataModel() {
return userDataModel;
}
public void setUserDataModel(UserDataModel userDataModel) {
this.userDataModel = userDataModel;
}
public User[] getSelectedUsers() {
return selectedUsers;
}
public void setSelectedUsers(User[] selectedUsers) {
this.selectedUsers = selectedUsers;
}
public User getSelectedUser() {
System.out.println("get-->"+selectedUser);
return selectedUser;
}
public void setSelectedUser(User selectedUser) {
System.out.println("set--->"+selectedUser);
this.selectedUser = selectedUser;
}
}
<!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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<body>
<h:form id="form">
<h:outputText value="PrimeFaces Demo - ShowUsers" />
<p:dataTable value="#{UserCRUDMB.userDataModel}" var="userObj"
selection="#{UserCRUDMB.selectedUsers}"
widgetVar="usersTbl">
<f:facet name="header">UserManagement</f:facet>
<p:column selectionMode="multiple"></p:column>
<p:column headerText="UserId">#{userObj.userId}</p:column>
<p:column headerText="UserName">#{userObj.userName}</p:column>
<p:column>
<p:commandButton value="Edit"
oncomplete="userEditDlg.show()"
update="form:userEditTbl">
<f:setPropertyActionListener target="#{UserCRUDMB.selectedUser}" value="#{userObj}"></f:setPropertyActionListener>
</p:commandButton>
</p:column>
<p:column>
<p:commandButton value="Delete" action="#{UserCRUDMB.deleteUser}"
update="usersTbl"
ajax="true">
<f:setPropertyActionListener target="#{UserCRUDMB.selectedUser}" value="#{userObj}"></f:setPropertyActionListener>
</p:commandButton>
</p:column>
<f:facet name="footer">
<p:commandButton value="Delete Selected" action="#{UserCRUDMB.deleteUsers}"
update="usersTbl"
ajax="true">
</p:commandButton>
</f:facet>
</p:dataTable>
<p:dialog widgetVar="userEditDlg" header="User Edit Form" hideEffect="explode"
minHeight="200" minWidth="300">
<h:panelGrid columns="2" id="userEditTbl" >
<h:outputLabel value="UserId" />
<h:outputText value="#{UserCRUDMB.selectedUser.userId}"/>
<h:outputLabel value="UserName" />
<h:inutText value="#{UserCRUDMB.selectedUser.userName}"/>
</h:panelGrid>
</p:dialog>
</h:form>
</body>
</html>
Thanks,
Siva
If you are using ajax, the request scope ist not the "ideal" scope since the bean will be recreated for each request. This can be the reason that selectedUser is null. Use the view scope (#ViewScoped) instead.