JSF Tree Validation Form on change node - jsf

I have a class Document for create a Tree with a list of document objects.
public class Document implements Serializable {
private String name;
private String size;
private List<Field> fields;
public Document(String name, String size, String type) {
this.name = name;
this.size = size;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSize() {
return size;
}
public void setSize(String size) {
this.size = size;
}
public List<Field> getFields() {
return fields;
}
public void setFields(List<Field> fields) {
this.fields = fields;
}
}
Also I have a Field class for store relevant information in documents
public class Field implements Serializable {
private int fieldIndex;
private String label;
private String value;
private List<Values> list;
public Field() {
}
public int getFieldIndex() {
return fieldIndex;
}
public void setFieldIndex(int fieldIndex) {
this.fieldIndex = fieldIndex;
}
public Field(String label) {
this.label = label;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public List<Values> getList() {
return list;
}
public void setList(List<Values> list) {
this.list = list;
}
}
My ManagedBean create a tree with some documents and store some data for each document. When i select the tree node, it's show a dynamic form with every field and inputs for enter some value.
#ManagedBean(name="treeSelectionView")
#ViewScoped
public class SelectionView implements Serializable {
private TreeNode root1;
private TreeNode selectedNode;
private String email;
private List<Field> fields;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
#PostConstruct
public void init() {
TreeNode root = new DefaultTreeNode(new Document("Files", "-", "Folder"), null);
TreeNode documents = new DefaultTreeNode(new Document("Documents", "-", "Folder"), root);
Field f1=new Field();
Field f2=new Field();
Field f3=new Field();
f1.setLabel("email");
f1.setValue("");
f2.setLabel("doc");
f2.setValue("");
f3.setLabel("otro");
f3.setValue("");
List<Field> fields=new ArrayList<Field>();
fields.add(f1);
fields.add(f2);
fields.add(f3);
List<Field> fields1=new ArrayList<Field>();
f1=new Field();
f2=new Field();
f3=new Field();
f1.setLabel("email");
f1.setValue("");
f2.setLabel("doc");
f2.setValue("");
f3.setLabel("otro");
f3.setValue("");
fields1.add(f1);
fields1.add(f2);
fields1.add(f3);
List<Field> fields2=new ArrayList<Field>();
f1=new Field();
f2=new Field();
f3=new Field();
f1.setLabel("email");
f1.setValue("");
f2.setLabel("doc");
f2.setValue("");
f3.setLabel("otro");
f3.setValue("");
fields2.add(f1);
fields2.add(f2);
fields2.add(f3);
//Documents
Document d1= new Document("Expenses.doc", "30 KB", "Word Document");
Document d2=new Document("Resume.doc", "10 KB", "Word Document");
Document d3=new Document("RefDoc.pages", "40 KB", "Pages Document");
d1.setFields(fields);
d2.setFields(fields1);
d3.setFields(fields2);
TreeNode expenses = new DefaultTreeNode("document",d1, documents);
TreeNode resume = new DefaultTreeNode("document", d2, documents);
TreeNode refdoc = new DefaultTreeNode("document",d3 , documents);
documents.setExpanded(true);
root1 = root;
root1.setExpanded(true);
}
public void onNodeDocumentSelect(NodeSelectEvent nodeSelected) {
// fields=((Document)nodeSelected.getTreeNode().getData()).getFields();
fields=((Document)selectedNode.getData()).getFields();
}
public TreeNode getRoot1() {
return root1;
}
public TreeNode getSelectedNode() {
return selectedNode;
}
public void setSelectedNode(TreeNode selectedNode) {
this.selectedNode = selectedNode;
}
public List<Field> getFields() {
return fields;
}
public void setFields(List<Field> fields) {
this.fields = fields;
}
}
My JSF looks like
<!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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>Default title</title>
</h:head>
<h:body>
<h:panelGrid columns="2">
<h:form id="treeForm">
<p:panel id="panel22" header="Documents" style="height:400px">
<p:growl id="msgs" showDetail="true" />
<p:tree value="#{treeSelectionView.root1}" var="doc" selectionMode="single" selection="#{treeSelectionView.selectedNode}" >
<p:ajax process="#this" event="select" update=":myForm:dymanicForm" listener="#{treeSelectionView.onNodeDocumentSelect}" />
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<h:outputText value="#{doc.name}"/>
</p:treeNode>
<p:treeNode type="document" icon="ui-icon-document" >
<h:outputText value="#{doc.name}" />
</p:treeNode>
</p:tree>
</p:panel>
</h:form>
<h:form id="myForm">
<p:panel id="panel222" header="Info Doccs" style="height:400px">
<p:panel id="dymanicForm" >
<ui:repeat value="#{treeSelectionView.fields}" var="componentMetadata">
<h:panelGrid columns="3">
<h:outputText value="#{componentMetadata.label}"/>:
<h:inputText id="field" value="#{componentMetadata.value}"
required="true" label="#{componentMetadata.label}"/>
<h:message for="field" style="color:red" /></h:panelGrid>
</ui:repeat>
</p:panel>
<h:commandButton value="Submit" action="result" />
</p:panel>
</h:form>
</h:panelGrid>
</h:body>
</html>
When I press the submit button the values are submitted and store in each field, also the validations are fired. But I really need remove the submit button and validate the form when i lost focus every node. By example if i am in the first node validate the form only when i lost focus , but if the form validation fail i need to stay in this node.
Really I appreciate any help you can give me.
Thanks a lot in advance.

I wanted to realize a similar view, and it took me quite some time to figure out.
The trick is not declaring the selection attribute on <p:tree, but just the selectionMode and manage the selection only with the listener, manually.
This causes the selection to be swapped in INVOKE_APPLICATION phase instead of UPDATE_MODEL_VALUES, preserving the right pane references in value expressions.
Furthermore, validation happens before selection swapping and, if fails, the selection swap is prevented.
I think this is exactly what you are looking for:
<h:form>
<p:layout fullPage="false" stateful="false" style="height:400px">
<p:layoutUnit position="center">
<p:tree id="tree" var="data" nodeVar="node" value="#{testTreeBean.root}"
selectionMode="single" dynamic="true" animate="true" highlight="true"
style="border: 0">
<p:ajax event="select" listener="#{testTreeBean.onSelect}" process="#form"
update="#this #form:details" />
<p:ajax event="expand" process="#this" />
<p:ajax event="collapse" process="#this" />
<p:treeNode expandedIcon="ui-icon-folder-open" collapsedIcon="ui-icon-folder-collapsed">
<p:outputPanel id="node">
<h:outputText value="#{data.someText1} - #{data.someText2}" />
</p:outputPanel>
</p:treeNode>
</p:tree>
</p:layoutUnit>
<p:layoutUnit position="east" size="65%" minSize="150">
<p:outputPanel id="details" style="padding: 1em">
<p:panelGrid columns="3" rendered="#{testTreeBean.data != null}">
<p:outputLabel value="someLabel1" for="#next" />
<p:inputText value="#{testTreeBean.data.someText1}" required="true" />
<p:message for="#previous" />
<p:outputLabel value="someLabel2" for="#next" />
<p:inputText value="#{testTreeBean.data.someText2}" required="true" />
<p:message for="#previous" />
</p:panelGrid>
<h:outputText value="please select a node in the left pane"
rendered="#{testTreeBean.data == null}" />
</p:outputPanel>
</p:layoutUnit>
</p:layout>
</h:form>
the bean:
#javax.faces.bean.ManagedBean
#javax.faces.bean.ViewScoped
public class TestTreeBean implements Serializable
{
private static final long serialVersionUID = 1L;
private TreeNode root;
private TreeNode selected;
// build a dummy tree...
#PostConstruct
public void init()
{
root = new DefaultTreeNode();
for(int i = 0; i < 5; i++)
{
SomeData data = new SomeData("node " + i, String.valueOf(System.currentTimeMillis()));
TreeNode node = new DefaultTreeNode(data, root);
for(int j = 0; j < 5; j++)
{
SomeData subData = new SomeData("subNode " + i + "." + j, String.valueOf(System.currentTimeMillis()));
#SuppressWarnings("unused")
TreeNode subNode = new DefaultTreeNode(subData, node);
}
}
}
// handle selection swap manually
public void onSelect(NodeSelectEvent event)
{
if(selected != null)
{
selected.setSelected(false);
}
selected = event.getTreeNode();
if(selected != null)
{
selected.setSelected(true);
}
}
// shortcut for getting the selected node data
public Object getData()
{
return selected == null ? null : selected.getData();
}
public TreeNode getSelected()
{
return selected;
}
public TreeNode getRoot()
{
return root;
}
}
finally, for completeness, the dummy data class:
public class SomeData implements Serializable
{
private String someText1;
private String someText2;
public SomeData()
{
super();
}
public SomeData(String someText1, String someText2)
{
super();
this.someText1 = someText1;
this.someText2 = someText2;
}
public String getSomeText1()
{
return someText1;
}
public void setSomeText1(String someText1)
{
this.someText1 = someText1;
}
public String getSomeText2()
{
return someText2;
}
public void setSomeText2(String someText2)
{
this.someText2 = someText2;
}
}
Happy gardening :)

Related

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?

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 :)

primefaces some components blank

I created a local website to import a string of GPS coordinates.
The layout is basic but consists mostly of primefaces components:
p:layouts
p:layoutUnit
p:selectOneList
p:gMap
p:lineChart
after some coding I noticed the gMap and lineChart weren't working anymore. At first I thought it was cause of the empty objects related to it (defaultMapModel for gMap and CartesianChartModel for lineChart). Even creating new objects and associating example data to it, these components stay blank.
Even removing the model attribute in the gMap doesn't seem to work.
Here are the codes I think matters:
index.xhtml:
<p:layoutUnit position="west" size="255" header="Options" resizable="false" closable="false" collapsible="true">
<div class="row-fluid">
<h4><i class="icon-calendar icon-white"></i>Calendar</h4>
<p:calendar mode="inline" id="inlineCal"/>
</div>
<div class="row-fluid">
<h4><i class="icon-random icon-white"></i>Tracks</h4>
<h:form prependId="false">
<p:selectOneListbox id="basic" style="width: 97%;" value="#{geoTrackController.geoTrack}">
<f:selectItems value="#{geoTrackController.allGeoTracks}" itemLabel="#{geoTrackController.geoTrack.id}" itemValue="#{geoTrackController.geoTrack.id}" />
</p:selectOneListbox>
</h:form>
</div>
</p:layoutUnit>
<p:layoutUnit position="center">
<p:layout fullPage="false">
<p:layoutUnit position="south" size="200" header="Speed (km/h)" resizable="false" closable="false" collapsible="true">
<p:lineChart id="linear" value="#{geoTrackController.linearModel}" legendPosition="e" zoom="true" minY="0" maxY="130" style="height:140px" widgetVar="chart" />
</p:layoutUnit>
<p:layoutUnit position="center">
<p:gmap id="geomap" center="50.52, 4.22" zoom="7" type="HYBRID" style="width:100%;height:97%;" model="#{geoTrackController.mapModel}" streetView="true" />
</p:layoutUnit>
</p:layout>
</p:layoutUnit>
Controller
#Named
#SessionScoped
public class GeoTrackController implements Serializable {
#EJB
private GeoTrackBean tbean;
private GeoTrack geoTrack = new GeoTrack();
private CartesianChartModel linearModel;
private MapModel map;
;
private String center = "50.8333, 4";
private String gpsDump;
#PostConstruct
public void init() {
createMapModel();
createLinearModel();
}
public GeoTrackController() {
}
public GeoTrack getGeoTrack() {
return geoTrack;
}
public void setGeoTrack(GeoTrack geoTrack) {
this.geoTrack = geoTrack;
}
public void trackChangeEvent(ValueChangeEvent e) {
createMapModel();
createLinearModel();
}
public List<GeoTrack> getAllGeoTracks() {
return tbean.getAllGeoTracks();
}
public String getGpsDump() {
return gpsDump;
}
public void setGpsDump(String gpsDump) {
this.gpsDump = gpsDump;
}
public String getCenter() {
return center;
}
public void submit() {
tbean.addOrUpdateGeoTrack(geoTrack);
createMapModel();
createLinearModel();
}
public MapModel getMapModel() {
return map;
}
public void onPolylineSelect(OverlaySelectEvent event) {
addMessage(new FacesMessage(FacesMessage.SEVERITY_INFO, "Polyline Selected", null));
}
public void addMessage(FacesMessage message) {
FacesContext.getCurrentInstance().addMessage(null, message);
}
public CartesianChartModel getLinearModel() {
return linearModel;
}
private void createMapModel() {
map = new DefaultMapModel();
if (this.geoTrack != null) {
Polyline path = new Polyline();
LatLng temp = new LatLng(0.00, 0.00);
for (GeoCoordinate c : this.geoTrack.getCoordinates()) {
LatLng coord = new LatLng(c.getLatitude(), c.getLongitude());
if (!temp.equals(coord)) {
path.getPaths().add(coord);
}
}
path.setStrokeWeight(4);
path.setStrokeColor("#FF9900");
path.setStrokeOpacity(0.7);
map.addOverlay(path);
}
}
private void createLinearModel() {
linearModel = new CartesianChartModel();
LineChartSeries speedChart = new LineChartSeries();
speedChart.setLabel("Speed");
if (this.geoTrack != null) {
for (GeoCoordinate c : this.geoTrack.getCoordinates()) {
speedChart.set(c.getDateTime().toString(), c.getSpeed());
}
linearModel.addSeries(speedChart);
} else {
speedChart.set(new Date(), 0);
}
}
}

Primefaces Datatable Selection Object

I have a question to the Primefaces Datatable, especially to the Selection Object.
In my following Code I get always Null for the Variable "Selected Question" which is bound to the Datatable with Selection.
The jsf as followed:
<?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" xml:lang="en" lang="en"
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">
<ui:composition template="mainTemplate.xhtml">
<ui:define name="contentTitle">Your Questions</ui:define>
<ui:define name="content">
<h:form id="formAllQuestion">
<p:growl id="allQuestionGrowl" showDetail="true"/>
<p:dataTable id="allQuestionsTable" var="question" value="#{allQuestionBean.allQuestionDataHelper}" paginator="true" rows="10"
selection="#{allQuestionBean.selectedQuestion}" selectionMode="single">
<p:ajax event="rowSelect" listener="#{allQuestionBean.onRowSelect}" update=":formAllQuestion:AnswerToQuestionDialogTable :formAllQuestion:allQuestionGrowl"
oncomplete="questDialog.show()"/>
<p:ajax event="rowUnselect" listener="#{allQuestionBean.onRowUnselect}" update=":formAllQuestion:allQuestionGrowl"/>
<f:facet name="header">Select a Row to display your Question Details</f:facet>
<p:column headerText="QuestionID">
#{question.questionId}
</p:column>
<p:column headerText="Question Name">
#{question.questionName}
</p:column>
<p:column headerText="Question Description">
#{question.questionText}
</p:column>
<p:column headerText="Question Short Description">
#{question.questionShortText}
</p:column>
<p:column headerText="Author">
#{question.professor.profSurename} #{question.professor.profName}
</p:column>
</p:dataTable>
<p:dialog header="Question Details" widgetVar="questionDialog" resizable="true" id="questDialog"
showEffect="fade" hideEffect="fade" modal="true">
<p:dataTable id="AnswerToQuestionDialogTable" var="answer" value="#{allQuestionBean.answers}">
<f:facet name="header">
Hier kommt der QR_Code rein!
#{allQuestionBean.selectedQuestion.questionId} - #{allQuestionBean.selectedQuestion.questionName}
</f:facet>
<p:column headerText="Answer">
<h:outputText value="#{answer.answerText}"/>
</p:column>
<p:column headerText="Counts For this Answer">
<h:outputText value="Bis jetz noch nix!"/>
</p:column>
</p:dataTable>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>
</html>
And the associated Bean Class (AllQuestionBean.class):
#ManagedBean(name = "allQuestionBean")
#ViewScoped
public class AllQuestionBean implements Serializable {
private static final long serialVersionUID = 7038894302985973905L;
#ManagedProperty(value = "#{questionDAO}")
private QuestionDAO questionDAO;
#ManagedProperty(value = "#{profSession.professor}")
private Professor professor;
#ManagedProperty(value = "#{answerDAO}")
private AnswerDAO answerDAO;
#ManagedProperty(value = "#{answeredDAO}")
private AnsweredDAO answeredDAO;
private List<Question> questions;
private Question selectedQuestion;
private List<Answer> answers;
private AllQuestionDataHelper allQuestionDataHelper;
public AllQuestionBean(){
System.out.println("Starting Bean: "+this.getClass().getName());
}
#PostConstruct
public void initVariables(){
questions = questionDAO.readByProfessor(professor);
}
public void onRowSelect(SelectEvent event) {
FacesMessage msg = new FacesMessage("Question Selected", selectedQuestion.getQuestionId()+" -- "+selectedQuestion.getQuestionName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
public void onRowUnselect(UnselectEvent event) {
FacesMessage msg = new FacesMessage("Question Selected", selectedQuestion.getQuestionId()+" -- "+selectedQuestion.getQuestionName());
FacesContext.getCurrentInstance().addMessage(null, msg);
}
//---GETTER and SETTER
public AllQuestionDataHelper getAllQuestionDataHelper() {
allQuestionDataHelper = new AllQuestionDataHelper(questions);
return allQuestionDataHelper;
}
public void setAllQuestionDataHelper(AllQuestionDataHelper allQuestionDataHelper) {
this.allQuestionDataHelper = allQuestionDataHelper;
}
public QuestionDAO getQuestionDAO() {
return questionDAO;
}
public void setQuestionDAO(QuestionDAO questionDAO) {
this.questionDAO = questionDAO;
}
public Professor getProfessor() {
return professor;
}
public void setProfessor(Professor professor) {
this.professor = professor;
}
public AnswerDAO getAnswerDAO() {
return answerDAO;
}
public void setAnswerDAO(AnswerDAO answerDAO) {
this.answerDAO = answerDAO;
}
public AnsweredDAO getAnsweredDAO() {
return answeredDAO;
}
public void setAnsweredDAO(AnsweredDAO answeredDAO) {
this.answeredDAO = answeredDAO;
}
public List<Question> getQuestions() {
return questions;
}
public void setQuestions(List<Question> questions) {
this.questions = questions;
}
public Question getSelectedQuestion() {
System.out.println("getSelectedQuestion");
return selectedQuestion;
}
public void setSelectedQuestion(Question selectedQuestion) {
System.out.println("Set selected Question: "+selectedQuestion);
this.selectedQuestion = selectedQuestion;
}
public List<Answer> getAnswers() {
answers = answerDAO.getAllAnswersForQuestion(selectedQuestion);
return answers;
}
public void setAnswers(List<Answer> answers) {
this.answers = answers;
}
}
The Data Modell:
public class AllQuestionDataHelper extends ListDataModel<Question> implements SelectableDataModel<Question> {
public AllQuestionDataHelper() {
}
public AllQuestionDataHelper(List<Question> list) {
super(list);
}
#Override
public Object getRowKey(Question question) {
if(!(question == null)){
System.out.println("Your Questions --> Getting RowKey");
System.out.println("RowKey: "+question);
System.out.println("RowKey: "+question.getQuestionId());
}else{
System.out.println("Warning Row Key is null");
}
return question.getQuestionId();
}
#Override
public Question getRowData(String rowKey) {
System.out.println("Your Questions --> Getting RowData");
System.out.println("RowData: "+rowKey);
List<Question> questionList = (List<Question>) getWrappedData();
for(Question q : questionList){
if(rowKey.equals(q.getQuestionId())){
System.out.println("Returning "+q.getQuestionId());
return q;
}
}
return null;
}
}
I debugged a few runs and mentioned that the Variable "selectedQuestion" in AllQuestionBean.class is never set. Will say, the event Variable in "onRowSelect" holds a NULL-Object.
As you can see there are two Datatables in the *.xhtml. The first one will load normally, no problems. The onClick-Method of the Bean should launch a Dialog with the Second Datatable, but will quit with a Nullpointer.
For the Datatable I followed the Tutorial at Primefaces (http://www.primefaces.org/showcase-labs/ui/datatableRowSelectionInstant.jsf)
Use rowKey attribute on p:dataTable.
rowKey is a unique Identifier that helps Primefaces engine to return the selected Object based on selection.
Usually the value you supply to the rowKey attribute is the unique property of the POJO that you are populating in to p:dataTable.
If you don't have any such unique fields in your POJO. Then its always useful to make one, for example: int rowId;, which you might increment and put in to POJO while you adding them to the List.

Resources