ValueChangeEvent for primefaces spinner is null - jsf

I'm using Primefaces and spinner component. I want to detect in changEvent method which button of spinner is clicked. I hoped I would get oldValue and newValue but the ValueChangeEvent is null. I am new in Java EE. could some body help me. my English is also not so good.
this is a part of my index.xhtml:
<h:form>
<h:panelGrid columns="2" cellpadding="5" styleClass="ui-grid">
<h:outputLabel for="ajaxSpinner" value="Ajax Spinner: " />
<p:outputPanel>
<p:spinner id="ajaxSpinner" value="#{spinnerView.number5}" >
<p:ajax event="valueChange" update="ajaxSpinnerValue" process="#this" listener="#{spinnerView.changeEvent(event)}" />
</p:spinner>
<h:outputText id="ajaxSpinnerValue" value="#{spinnerView.number5}" style="padding-left: 10px" />
</p:outputPanel>
</h:panelGrid>
</h:form>
and this is Bean-Class
package test.ctrl;
import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.ValueChangeEvent;
import javax.inject.Named;
#Named("spinnerView")
#SessionScoped
public class WebBean implements Serializable{
private int number1;
private int number2;
private int number3;
private int number4;
private int number5;
public int getNumber1() {
return number1;
}
public void setNumber1(int number1) {
this.number1 = number1;
}
public int getNumber2() {
return number2;
}
public void setNumber2(int number2) {
this.number2 = number2;
}
public int getNumber3() {
return number3;
}
public void setNumber3(int number3) {
this.number3 = number3;
}
public int getNumber4() {
return number4;
}
public void setNumber4(int number4) {
this.number4 = number4;
}
public int getNumber5() {
return number5;
}
public void setNumber5(int number5) {
this.number5 = number5;
}
public void callBean(){
System.out.println("Ausgabe" + number5);
}
public void changeEvent(ValueChangeEvent ev){
System.out.println("Ausgabe:"+ev.getOldValue() +"--" +ev.getNewValue());
}
}

I change p:spiner and p:ajax tags as follow:
<p:spinner id="ajaxSpinner" value="#{spinnerView.number5}" valueChangeListener="#{spinnerView.changeEvent}" >
<p:ajax update="#form" process="#this, ajaxSpinner" />
</p:spinner>

Related

Primefaces Datatable filtering issue for drop down as data input

I have a drop down (p:selectOneMenu) as the input field in the Primefaces 8.0 datatable row, after I select the value in the drop down, if I sort it the selected value can be kept after ajax submit. However if I input a filter that filter 0 rows, and then I clear the filter, the selected value in the drop down disappear:
updated base on Kukeltje's request for adding input text:
Select the drop down value
input the filter so that all the rows are filter out
clear the filter, the selected value disappear
My backing bean:
package sample;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
#Named
#SessionScoped
public class SampleBean implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 5307652891294044974L;
private static final Map<String, String> dropDown = new HashMap<>();
static {
dropDown.put("K1", "K1");
dropDown.put("K2", "K2");
dropDown.put("K3", "K3");
}
public Map<String, String> getDropDown() {
return dropDown;
}
private List<TableObject> tableObjects = Arrays.asList(new TableObject[] {new TableObject(), new TableObject()});
public List<TableObject> getTableObjects() {
return tableObjects;
}
public void setTableObjects(List<TableObject> tableObjects) {
this.tableObjects = tableObjects;
}
public static class TableObject
{
private String dd;
private String inputText;
public String getDd() {
return dd;
}
public void setDd(String dd) {
this.dd = dd;
}
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
}
}
}
My facelet:
<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:o="http://omnifaces.org/ui"
xmlns:of="http://omnifaces.org/functions">
<h:head>
<title>Hello World JSF 2.3</title>
</h:head>
<h:body>
<h:form>
<p:dataTable var="item" value="#{sampleBean.tableObjects}"
widgetVar="itemTable">
<p:ajax event="sort" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="page" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="filter" process="#this" update="#this" global="false"
skipChildren="false" />
<p:column headerText="Dropdown" sortBy="#{item.dd}"
filterBy="#{item.dd}" filterMatchMode="contains">
<p:selectOneMenu id="Dropdown" value="#{item.dd}" required="false"
label="Dropdown" style="width: 90%">
<f:selectItem itemValue="#{null}" itemLabel="" />
<f:selectItems value="#{sampleBean.dropDown.entrySet()}"
var="entry" itemValue="#{entry.value}" itemLabel="#{entry.key}" />
</p:selectOneMenu>
</p:column>
<p:column id="InputTextHeader" headerText="Input Text"
sortBy="#{item.inputText}" filterBy="#{item.inputText}"
filterMatchMode="contains">
<p:inputText id="InputText" value="#{item.inputText}" />
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
I push my testing project to github, in case you want to test it
git clone https://github.com/saycchai/jsf-test.git
cd jsf-test
chmod +x *.sh
./buildAndRun.sh
for payara server:
browse: http://localhost:8080/index.xhtml
for other server:
http://localhost:8080/jsf-test/index.xhtml
Finally I found a work around solution as follows:
I added a phase listener, if the filter submit 0 row (pass as a request parameter, please see the onstart part in the facelet), then backup the Dd value to previousDd before the APPLY_REQUEST_VALUES phase and set the backup value previousDd back to Dd before the RENDER_RESPONSE phase, code as follows:
Backing Bean
package sample;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.enterprise.context.SessionScoped;
import javax.inject.Named;
import javax.persistence.Transient;
#Named
#SessionScoped
public class SampleBean implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = 5307652891294044974L;
private static final Map<String, String> dropDown = new HashMap<>();
static {
for(int i=1; i<10; i++) {
dropDown.put("K"+i, "K"+i);
}
}
public Map<String, String> getDropDown() {
return dropDown;
}
private List<TableObject> tableObjects = Arrays.asList(new TableObject[] {new TableObject(), new TableObject(), new TableObject(), new TableObject()});
public List<TableObject> getTableObjects() {
return tableObjects;
}
public void setTableObjects(List<TableObject> tableObjects) {
this.tableObjects = tableObjects;
}
public static class TableObject
{
private String dd;
private String inputText;
public String getDd() {
return dd;
}
public void setDd(String dd) {
this.dd = dd;
}
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
}
#Transient
private String previousDd;
public String getPreviousDd() {
return previousDd;
}
public void setPreviousDd(String previousDd) {
this.previousDd = previousDd;
}
}
}
Facelet
<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"
>
<h:head>
<title>Hello World JSF 2.3</title>
</h:head>
<h:body>
<h:form id="form">
<p:dataTable id="itemTable" var="item" value="#{sampleBean.tableObjects}"
widgetVar="itemTable"
paginator="true"
>
<p:ajax event="sort" process="#this" update="#this"
skipChildren="false" />
<p:ajax event="page" process="#this" update="#this"
skipChildren="false"
/>
<p:ajax event="filter" process="#this" update="#this" global="false"
skipChildren="false"
onstart="cfg.ext.params.push({name: 'tableFilterCount', value: PF('itemTable').paginator.cfg.rowCount});"
/>
<p:column id="DropdownHeader" headerText="Dropdown" sortBy="#{item.dd}"
filterBy="#{item.dd}" filterMatchMode="contains">
<p:selectOneMenu id="Dropdown" value="#{item.dd}" required="false"
label="Dropdown" style="width: 90%">
<f:selectItem itemValue="#{null}" itemLabel="" />
<f:selectItems value="#{sampleBean.dropDown.entrySet()}"
var="entry" itemValue="#{entry.value}" itemLabel="#{entry.key}" />
</p:selectOneMenu>
</p:column>
<p:column id="InputTextHeader" headerText="Input Text"
sortBy="#{item.inputText}" filterBy="#{item.inputText}"
filterMatchMode="contains">
<p:inputText id="InputText" value="#{item.inputText}" >
<p:ajax />
</p:inputText>
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
Phase Listener
package sample;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import org.primefaces.component.datatable.DataTable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.SampleBean.TableObject;
public class SamplePhaseListener implements PhaseListener {
/**
*
*/
private static final long serialVersionUID = 5273254619684337785L;
private Logger logger = LoggerFactory.getLogger(this.getClass());
public void afterPhase(PhaseEvent event) {
}
public void beforePhase(PhaseEvent event) {
if(event.getPhaseId() == PhaseId.APPLY_REQUEST_VALUES) {
prettyPrint("----------------start of Before "+event.getPhaseId().getName()+"------------------------------", 0);
String tableFilterCount = event.getFacesContext().getExternalContext().getRequestParameterMap().get("tableFilterCount");
if(tableFilterCount != null && "0".equals(tableFilterCount)) {
//backup the previous value first
DataTable table = (DataTable) event.getFacesContext().getViewRoot().findComponent("form:itemTable");
for (int index = 0; index < table.getRowCount(); index++) {
table.setRowIndex(index);
Object rowData = table.getRowData();
if(rowData != null) {
TableObject tableObject = (TableObject) rowData;
logger.info(" before backup to previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
tableObject.setPreviousDd(tableObject.getDd());
logger.info(" after backup to previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
}
}
}
prettyPrint("----------------end of Before "+event.getPhaseId().getName()+"------------------------------", 0);
}
if(event.getPhaseId() == PhaseId.RENDER_RESPONSE) {
prettyPrint("----------------start of Before " + event.getPhaseId().getName() + "------------------------------", 0);
String tableFilterCount = event.getFacesContext().getExternalContext().getRequestParameterMap().get("tableFilterCount");
if(tableFilterCount != null && "0".equals(tableFilterCount)) {
//restore the Dd from previous value
DataTable table = (DataTable) event.getFacesContext().getViewRoot().findComponent("form:itemTable");
for (int index = 0; index < table.getRowCount(); index++) {
table.setRowIndex(index);
Object rowData = table.getRowData();
if(rowData != null) {
TableObject tableObject = (TableObject) rowData;
logger.info(" before restore from previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
tableObject.setDd(tableObject.getPreviousDd());
logger.info(" after restore from previousDd, dd: {}, previousDd: {}", tableObject.getDd(), tableObject.getPreviousDd());
}
}
}
prettyPrint("----------------end of Before "+event.getPhaseId().getName()+"------------------------------", 0);
}
}
public PhaseId getPhaseId() {
return PhaseId.ANY_PHASE;
}
public static final String IDENT = " ";
private void prettyPrint(String str, int depth) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < depth; i++)
sb.append(IDENT);
sb.append(str + "\n");
logger.trace(sb.toString());
}
}
faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_3.xsd"
version="2.3">
<lifecycle>
<phase-listener>sample.SamplePhaseListener</phase-listener>
</lifecycle>
</faces-config>

Ajax is not working after lending the page after navigation from main menu. It works only after using submit button once

What I doing is just an application where the selected option display in the textArea. But Ajax is not working after lending the page after navigation from the main menu on this page. That function only works after using the submit button.
Below is my JSF page code
<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:p="http://primefaces.org/ui"
template="/WEB-INF/template.xhtml">
<ui:define name="title">
Ajax Framework - <span class="subitem">Basic</span>
</ui:define>
<ui:define name="description">
This example demonstrates a simple but common usage of posting the form, updating the backend value and displaying the output with ajax.
</ui:define>
<ui:define name="implementation">
<h:form>
<p:panel id="panel" header="Form" style="margin-bottom:10px;">
<p:messages>
<p:autoUpdate />
</p:messages>
<h:panelGrid columns="2" style="margin-bottom:10px" cellpadding="5">
<p:outputLabel for="lazy" value="Lazy:" />
<p:selectOneMenu id="lazy" value="#{selectOneMenuView.option}" lazy="true" style="width:125px">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems value="#{selectOneMenuView.options}" />
<f:ajax event="change" listener="#{selectOneMenuView.onChange}" execute="#this" render="textarea1"/>
</p:selectOneMenu>
</h:panelGrid>
<p:commandButton value="Submit" update="display" oncomplete="PF('dlg').show()" icon="ui-icon-check" />
<p:dialog header="Values" modal="true" showEffect="bounce" widgetVar="dlg" resizable="false">
<p:panelGrid columns="2" id="display" columnClasses="label,value">
<h:outputText value="Lazy:" />
<h:outputText value="#{selectOneMenuView.option}" />
</p:panelGrid>
</p:dialog>
<h3>AutoResize</h3>
<p:inputTextarea id="textarea1" value="#{selectOneMenuView.inputTextArea}" rows="6" cols="33" />
</p:panel>
</h:form>
</ui:define>
</ui:composition>
And my managed bean is as below
package org.primefaces.showcase.view.input;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.model.SelectItem;
import javax.faces.model.SelectItemGroup;
import org.primefaces.showcase.domain.Theme;
import org.primefaces.showcase.service.ThemeService;
#ManagedBean
public class SelectOneMenuView {
private String console;
private String car;
private List<SelectItem> cars;
private String city;
private Map<String,String> cities = new HashMap<String, String>();
private Theme theme;
private List<Theme> themes;
private String option;
private List<String> options;
private String inputTextArea;
public String getInputTextArea() {
return inputTextArea;
}
public void setInputTextArea(String inputTextArea) {
this.inputTextArea = inputTextArea;
}
#ManagedProperty("#{themeService}")
private ThemeService service;
#PostConstruct
public void init() {
//cars
SelectItemGroup g1 = new SelectItemGroup("German Cars");
g1.setSelectItems(new SelectItem[] {new SelectItem("BMW", "BMW"), new SelectItem("Mercedes", "Mercedes"), new SelectItem("Volkswagen", "Volkswagen")});
SelectItemGroup g2 = new SelectItemGroup("American Cars");
g2.setSelectItems(new SelectItem[] {new SelectItem("Chrysler", "Chrysler"), new SelectItem("GM", "GM"), new SelectItem("Ford", "Ford")});
cars = new ArrayList<SelectItem>();
cars.add(g1);
cars.add(g2);
//cities
cities = new HashMap<String, String>();
cities.put("New York", "New York");
cities.put("London","London");
cities.put("Paris","Paris");
cities.put("Barcelona","Barcelona");
cities.put("Istanbul","Istanbul");
cities.put("Berlin","Berlin");
//themes
themes = service.getThemes();
//options
options = new ArrayList<String>();
for(int i = 0; i < 20; i++) {
options.add("Option " + i);
}
}
public String getConsole() {
return console;
}
public void setConsole(String console) {
this.console = console;
}
public String getCar() {
return car;
}
public void setCar(String car) {
this.car = car;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public Theme getTheme() {
return theme;
}
public void setTheme(Theme theme) {
this.theme = theme;
}
public List<SelectItem> getCars() {
return cars;
}
public Map<String, String> getCities() {
return cities;
}
public List<Theme> getThemes() {
return themes;
}
public void setService(ThemeService service) {
this.service = service;
}
public String getOption() {
return option;
}
public void setOption(String option) {
this.option = option;
}
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public void onChange(){
this.inputTextArea = this.option;
}
}
May I know why? Can anyone give me some guideline?

Programmatically adding selectonemenu

I have a problem with adding selectonemenu component of Primefaces at runtime.
I added the selectonemenu but it doesnt display the name or attrbt of the objects , it shows references of them.
Thank you for your time .
<ui:composition template="/pages/admin/admin.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<ui:define name="center">
<h:form id="openposition">
<h:panelGrid id="openpanelposition" columns="1">
<p:outputLabel value="#{menu['menu.admin.openposition.name']}"/>
<p:selectOneMenu id="positiontype" value="#{openPositionController.position}" converter="#{positionConverter}" panelStyle="width:180px"
effect="fade" var="u" style="width:160px" filter="true" filterMatchMode="startsWith">
<f:selectItems value="#{openPositionController.positionList}" var="position" itemLabel="#{position.name}" itemValue="#{position}" />
<p:column>
<h:outputText value="#{u.name}" />
</p:column>
</p:selectOneMenu>
<h:panelGrid id="unitgroup" columns="1">
<p:selectOneMenu id="higherunit" value="#{openPositionController.unit}" converter="#{unitConverter}" panelStyle="width:180px"
effect="fade" var="unit" style="width:160px" filter="true" filterMatchMode="startsWith"
valueChangeListener="#{openPositionController.selectunit}">
<f:selectItems value="#{openPositionController.unitList}" var="unit" itemLabel="#{unit.unitName}" itemValue="#{unit}" />
<p:ajax update="#this"/>
<p:column>
<h:outputText value="#{unit.unitName}" />
</p:column>
</p:selectOneMenu>
</h:panelGrid>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
package tr.com.innova.hrm.web.controller.menucontroller;
/**
* Created by mcan on 22/01/2015.
*/
import org.primefaces.component.selectonemenu.SelectOneMenu;
import org.primefaces.context.RequestContext;
import tr.com.innova.hrm.model.entity.Position;
import tr.com.innova.hrm.model.entity.Unit;
import tr.com.innova.hrm.service.api.business.PositionService;
import tr.com.innova.hrm.service.api.business.UnitService;
import tr.com.innova.hrm.web.converter.UnitConverter;
import javax.annotation.PostConstruct;
import javax.el.ELContext;
import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.component.UISelectItems;
import javax.faces.component.html.HtmlPanelGrid;
import javax.faces.component.html.HtmlPanelGroup;
import javax.faces.context.FacesContext;
import java.io.Serializable;
import java.util.List;
#ManagedBean(name = "openPositionController")
#ViewScoped
public class OpenPositionViewController implements Serializable{
private Position position;
private Unit unit;
private List<Position> positionList;
private List<Unit> unitList;
#ManagedProperty("#{positionService}")
private PositionService service;
#ManagedProperty("#{unitService}")
private UnitService unitService;
public UnitService getUnitService() {
return unitService;
}
public void setUnitService(UnitService unitService) {
this.unitService = unitService;
}
public Unit getUnit() {
return unit;
}
public void setUnit(Unit unit) {
this.unit = unit;
}
public List<Unit> getUnitList() {
return unitList;
}
public void setUnitList(List<Unit> unitList) {
this.unitList = unitList;
}
public Position getPosition() {
return position;
}
public void setPosition(Position position) {
this.position = position;
}
public List<Position> getPositionList() {
return positionList;
}
public void setPositionList(List<Position> positionList) {
this.positionList = positionList;
}
public PositionService getService() {
return service;
}
public void setService(PositionService service) {
this.service = service;
}
#PostConstruct
public void init()
{
positionList = service.loadAll();
unitList = unitService.getAllUnit();
FacesContext.getCurrentInstance().getViewRoot();
}
public void selectunit()
{
HtmlPanelGrid component = (HtmlPanelGrid) FacesContext.getCurrentInstance().getViewRoot().findComponent(":openposition:unitgroup");
SelectOneMenu oneMenu = new SelectOneMenu();
oneMenu.setRendered(true);
oneMenu.setConverter(new UnitConverter());
UISelectItems items = new UISelectItems();
ValueExpression expr = getValueExpression("#{openPositionController.unitList}");
items.setValueExpression("value", expr);
oneMenu.getChildren().add(items);
component.getChildren().add(oneMenu);
RequestContext context = RequestContext.getCurrentInstance();
context.update("openposition");
context.update("openposition:unitgroup");
}
private ValueExpression getValueExpression(String expression) {
ExpressionFactory expressionFactory = FacesContext.getCurrentInstance().getApplication().getExpressionFactory();
ELContext expressionContext = FacesContext.getCurrentInstance().getELContext();
return expressionFactory.createValueExpression(expressionContext, expression, Object.class);
}
}
Here is my answer for the future generations...
This is the way i've created a SelectOneMenu of PrimeFaces programmatically:
// Get context and expression factory
FacesContext context = FacesContext.getCurrentInstance();
ExpressionFactory ef = context.getApplication().getExpressionFactory();
// Create panel grid
HtmlPanelGrid grid = new HtmlPanelGrid();
grid.setColumns(2);
// Create the select label
OutputLabel comboLabel = new OutputLabel();
comboLabel.setValue(obj.getNameFilter());
comboLabel.setFor(cmpName);
grid.getChildren().add(comboLabel);
// The biding expression of the select
ValueExpression comboExpr = ef.createValueExpression(context.getELContext(),
"#{MbDinamicReports.valueCombo}", String.class);
// Create the select
SelectOneMenu comboBox = new SelectOneMenu();
comboBox.setId(cmpName);
comboBox.setValueExpression("value", comboExpr);
// Here the items are added
for (int i = 0; i < 3; i++) {
UISelectItem item = new UISelectItem();
item.setItemLabel("Label" + i);
item.setItemValue("value" + i);
comboBox.getChildren().add(item);
}
grid.getChildren().add(comboBox);

JSF/Primefaces issue when form field rendering depends on selectOneMenu

Form field rendering is depending on selected item in selectOneMenu.
Page:
<h:body>
<f:view>
<h:form>
<h:panelGrid>
<p:inputText value="#{user.username}"/>
<p:selectOneMenu value="#{user.moreInputs}"
required="true">
<p:ajax event="change"
update="moreInputGrid"/>
<f:selectItem itemLabel="" itemValue=""/>
<f:selectItems value="#{user.selectItems}"/>
</p:selectOneMenu>
</h:panelGrid>
<h:panelGrid id="moreInputGrid">
<p:inputText rendered="#{user.renderMoreInputs}"
value="#{user.name}"/>
</h:panelGrid>
<p:commandButton action="#{user.register}"
value="Register user"/>
</h:form>
</f:view>
</h:body>
Backing bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
#ManagedBean
#ViewScoped
public class User {
private String username;
private MoreInputs moreInputs;
private String name;
public enum MoreInputs {
YES,
NO
}
public boolean isRenderMoreInputs() {
return (moreInputs == MoreInputs.YES);
}
public SelectItem[] getSelectItems() {
SelectItem[] items = new SelectItem[2];
items[0] = new SelectItem(
MoreInputs.YES,
"yes");
items[1] = new SelectItem(
MoreInputs.NO,
"no");
return items;
}
public String register() {
return null;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public MoreInputs getMoreInputs() {
return moreInputs;
}
public void setMoreInputs(MoreInputs moreInputs) {
this.moreInputs = moreInputs;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Issue arrises if the client does page refresh after choosing an item causing form fields to render. Such form fields will not be rendered on page refresh, although they should. Plus, if client then tries to submit form, validation is skipped for those hidden fields and form is successfully processed.
Am I doing something wrong? Is there an elegant solution?

Datatable Row Selection Primefaces

I am trying to implement row selection for a datatable with primefaces, but when I click on a row, nothing displays. I've narrowed it down to the setter for the selected car is not getting called, but I do not know how to set this. Here's my code, can anybody help?
TableBean
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name="TableBean")
#ViewScoped
public class ViewCDeployments implements Serializable {
private static final long serialVersionUID = 2213388781051004157L;
private final static String[] colors;
private final static String[] manufacturers;
static {
colors = new String[10];
colors[0] = "Black";
colors[1] = "White";
colors[2] = "Green";
colors[3] = "Red";
colors[4] = "Blue";
colors[5] = "Orange";
colors[6] = "Silver";
colors[7] = "Yellow";
colors[8] = "Brown";
colors[9] = "Maroon";
manufacturers = new String[10];
manufacturers[0] = "Mercedes";
manufacturers[1] = "BMW";
manufacturers[2] = "Volvo";
manufacturers[3] = "Audi";
manufacturers[4] = "Renault";
manufacturers[5] = "Opel";
manufacturers[6] = "Volkswagen";
manufacturers[7] = "Chrysler";
manufacturers[8] = "Ferrari";
manufacturers[9] = "Ford";
}
private List<Car> cars;
private Car selectedCar;
private Car[] selectedCars;
private CarDataModel mediumCarsModel;
public ViewCDeployments() {
cars = new ArrayList<Car>();
populateRandomCars(cars, 50);
mediumCarsModel = new CarDataModel(cars);
}
public Car[] getSelectedCars() {
return selectedCars;
}
public void setSelectedCars(Car[] selectedCars) {
this.selectedCars = selectedCars;
}
public Car getSelectedCar() {
return selectedCar;
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
private void populateRandomCars(List<Car> list, int size) {
for(int i = 0 ; i < size ; i++)
list.add(new Car(getRandomModel(), getRandomYear(), getRandomManufacturer(), getRandomColor()));
}
private int getRandomYear() {
return (int) (Math.random() * 50 + 1960);
}
private String getRandomColor() {
return colors[(int) (Math.random() * 10)];
}
private String getRandomManufacturer() {
return manufacturers[(int) (Math.random() * 10)];
}
private String getRandomModel() {
return UUID.randomUUID().toString().substring(0, 8);
}
public CarDataModel getMediumCarsModel() {
return mediumCarsModel;
}
public List<Car> getCars() {
return cars;
}
}
Car.java
import java.io.Serializable;
public class Car implements Serializable {
/**
*
*/
private static final long serialVersionUID = 240545116337689611L;
private String model;
private int year;
private String manufacturer;
private String color;
private int price;
public Car(String model, int year, String manufacturer, String color) {
this.model = model;
this.year = year;
this.manufacturer = manufacturer;
this.color = color;
}
public Car(String model, int year, String manufacturer, String color, int price) {
this.model = model;
this.year = year;
this.manufacturer = manufacturer;
this.color = color;
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
#Override
public boolean equals(Object obj) {
if(obj == null)
return false;
if(!(obj instanceof Car))
return false;
Car compare = (Car) obj;
return compare.model.equals(this.model);
}
#Override
public int hashCode() {
int hash = 1;
return hash * 31 + model.hashCode();
}
#Override
public String toString() {
return "Car{" + "model=" + model + ", year=" + year + ", manufacturer=" + manufacturer + ", color=" + color + ", price=" + price + '}';
}
}
CarDataModel
import java.io.Serializable;
import java.util.List;
import javax.faces.model.ListDataModel;
import org.primefaces.model.SelectableDataModel;
public class CarDataModel extends ListDataModel<Car> implements SelectableDataModel<Car>, Serializable {
/**
*
*/
private static final long serialVersionUID = -5147159758418722534L;
public CarDataModel() {
}
public CarDataModel(List<Car> data) {
super(data);
}
#SuppressWarnings("unchecked")
#Override
public Car getRowData(String rowKey) {
//In a real app, a more efficient way like a query by rowKey should be implemented to deal with huge data
List<Car> cars = (List<Car>) getWrappedData();
for(Car car : cars) {
if(car.getModel().equals(rowKey))
return car;
}
return null;
}
#Override
public Object getRowKey(Car car) {
return car.getModel();
}
}
XHTML
<ui:composition 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:ui="http://java.sun.com/jsf/facelets">
<h:form id="form">
<p:dataTable id="cars" var="car" value="#{TableBean.mediumCarsModel}" paginator="true" rows="10"
selection="#{TableBean.selectedCar}">
<f:facet name="header">
RadioButton Based Selection
</f:facet>
<p:column selectionMode="single" style="width:18px" />
<p:column headerText="Model">
#{car.model}
</p:column>
<p:column headerText="Year">
#{car.year}
</p:column>
<p:column headerText="Manufacturer" >
#{car.manufacturer}
</p:column>
<p:column headerText="Color">
#{car.color}
</p:column>
<f:facet name="footer">
<p:commandButton id="viewCommand" value="View" icon="ui-icon-search"
update=":frmContent:form:displaySingle" oncomplete="singleCarDialog.show()"/>
</f:facet>
</p:dataTable>
<p:dialog id="dialog" header="Car Detail" widgetVar="singleCarDialog" resizable="false"
showEffect="fade" hideEffect="explode">
<h:panelGrid id="displaySingle" columns="2" cellpadding="4">
<f:facet name="header">
Header
</f:facet>
<h:outputText value="Model:" />
<h:outputText value="#{TableBean.selectedCar.model}" />
<h:outputText value="Year:" />
<h:outputText value="#{TableBean.selectedCar.year}" />
<h:outputText value="Manufacturer:" />
<h:outputText value="#{TableBean.selectedCar.manufacturer}" />
<h:outputText value="Color:" />
<h:outputText value="#{TableBean.selectedCar.color}" />
</h:panelGrid>
</p:dialog>
</h:form>
</ui:composition>
Just add to your datatable rowKey. Without this property selection won't work.
<p:dataTable id="cars" var="car" value="#{TableBean.mediumCarsModel}" paginator="true" rows="10" rowKey="#{car.manufacturer}" selection="#{TableBean.selectedCar}">
The rowKey must be the unique in the list of values.
I think you have added too much code.
See the example below :
test.xhml
<?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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
>
<h:head>
<title>PrimeFaces AJAX Enabled SelectOneMenu</title>
<style>
.ui-widget,.ui-widget .ui-widget {
font-size: 90% !important;
}
</style>
</h:head>
<h:body>
<h:body>
<h:form id="form">
<p:dataTable id="cars" var="car" value="#{testBean.cars}">
<p:column headerText="Model" style="width:24%">
<h:outputText value="#{car.model}" />
</p:column>
<p:column headerText="Year" style="width:24%">
<h:outputText value="#{car.year}" />
</p:column>
<p:column headerText="Manufacturer" style="width:24%">
<h:outputText value="#{car.manufacturer}" />
</p:column>
<p:column headerText="Color" style="width:24%">
<h:outputText value="#{car.color}" />
</p:column>
<p:column style="width:4%">
<p:commandButton id="selectButton" update=":form:display"
oncomplete="carDialog.show()" icon="ui-icon-search" title="View">
<f:setPropertyActionListener value="#{car}"
target="#{testBean.selectedCar}" />
</p:commandButton>
</p:column>
</p:dataTable>
<p:dialog header="Car Detail" widgetVar="carDialog" resizable="false"
id="carDlg" showEffect="fade" hideEffect="explode" modal="true">
<h:panelGrid id="display" columns="2" cellpadding="4"
style="margin:0 auto;">
<h:outputText value="Model:" />
<h:outputText value="#{testBean.selectedCar.manufacturer}"
style="font-weight:bold" />
</h:panelGrid>
</p:dialog>
</h:form>
</h:body>
</h:body>
</html>
BackBean
package com.jmxwebapp.mbeans;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "testBean")
#ViewScoped
public class CarBean {
private List<Car> cars;
private Car selectedCar;
public CarBean() {
cars = new ArrayList<Car>();
cars.add(new Car("Test", 2013, "Toyo", "Blue"));
cars.add(new Car("Test1", 2013, "Toyo", "Red"));
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
public Car getSelectedCar() {
return selectedCar;
}
public void setSelectedCar(Car selectedCar) {
this.selectedCar = selectedCar;
}
}
Car
package com.jmxwebapp.mbeans;
import java.io.Serializable;
public class Car implements Serializable {
/**
*
*/
private static final long serialVersionUID = 240545116337689611L;
private String model;
private int year;
private String manufacturer;
private String color;
private int price;
public Car(String model, int year, String manufacturer, String color) {
this.model = model;
this.year = year;
this.manufacturer = manufacturer;
this.color = color;
}
public Car(String model, int year, String manufacturer, String color, int price) {
this.model = model;
this.year = year;
this.manufacturer = manufacturer;
this.color = color;
this.price = price;
}
public String getModel() {
return model;
}
public void setModel(String model) {
this.model = model;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getManufacturer() {
return manufacturer;
}
public void setManufacturer(String manufacturer) {
this.manufacturer = manufacturer;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
#Override
public boolean equals(Object obj) {
if (obj == null)
return false;
if (!(obj instanceof Car))
return false;
Car compare = (Car) obj;
return compare.model.equals(this.model);
}
#Override
public int hashCode() {
int hash = 1;
return hash * 31 + model.hashCode();
}
#Override
public String toString() {
return "Car{" + "model=" + model + ", year=" + year + ", manufacturer=" + manufacturer + ", color=" + color + ", price=" + price + '}';
}
}
**Try above it should work**
The problem is with dialog component. In your dialog component You're using the same object where store selected car object (selectedCar). Pages are renderized from top to bottom. Therefore when You make clic the value stored is selectedCar object from dialog component. This value is initialized in null firstly.
For this You should be other object in your dialog component.
Notice that when you are using your beans you include them "inside" the html component, like:
<p:column headerText="Model">
#{car.model}
</p:column>
When you should be incluiding the bean inside the tag in the value option:
<p:column headerText="Model" value="#{car.model}>
</p:column>
Hope it works :)

Resources