I have very strange problem. I can't use function in second button.
Steps:
1. Write forename and surename.
2. Click "find" button. Result: items in datatable.
3. Click "TEMPPP" only refresh page.
I have to use function sendUserInformation()
Administrator.xhtml
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:ace="http://www.icefaces.org/icefaces/components"
template="/WEB-INF/templates/template.xhtml">
<ui:define name="menuItems">
</ui:define>
<ui:define name="logedContent">
<h:form id="form1t">
<center><h:outputLabel value="#{msg.find_employee}"/></center>
<table class="tableGeneral">
<tr>
<td><h:outputLabel value="#{msg.forename}*"/></td>
<td>
<h:inputText id="name1" value="#{administrationController.forename}">
<f:validator validatorId="DefaultStringValidator"/>
</h:inputText>
</td>
<td>
<h:message styleClass="error" for="name1"/>
</td>
</tr>
<tr>
<td><h:outputLabel value="#{msg.surename}*"/></td>
<td>
<h:inputText id="name2" value="#{administrationController.surename}">
<f:validator validatorId="DefaultStringValidator"/>
</h:inputText>
</td>
<td>
<h:message styleClass="error" for="name2"/>
</td>
</tr>
<tr>
<td colspan="2">
<h:commandButton styleClass="buttonGeneral" value="#{msg.find}" >
<!-- <f:ajax event="click" execute="name1 name2" render=":form1t:form2:tab" listener="#{administrationController.find_employee()}"/> -->
<f:ajax event="click" execute="name1 name2" render="#all" listener="#{administrationController.find_employee()}"/>
</h:commandButton>
</td>
</tr>
</table>
</h:form>
<hr/>
<br/>
<h:form id="form2">
<center><h:outputLabel value="#{msg.found}"/></center>
<h:dataTable id="tab" value="#{administrationController.foundUsers}" styleClass="tableGeneral" var="o">
<h:column>
<f:facet name="header"><h:outputLabel value="#{msg.forename}"/></f:facet>
<h:outputText value="#{o.forename}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputLabel value="#{msg.surename}"/></f:facet>
<h:outputText value="#{o.surename}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputLabel value="#{msg.job}"/></f:facet>
<h:outputText value="#{o.job}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputLabel value="#{msg.user}"/></f:facet>
<h:outputText value="#{o.login}"/>
</h:column>
<h:column>
<f:facet name="header"><h:outputLabel value="#{msg.activated}"/></f:facet>
<h:outputText value="#{msg.yes}" rendered="#{o.activated}"/>
<h:outputText value="#{msg.no}" rendered="#{!o.activated}"/>
</h:column>
<h:column>
<!-- <h:commandButton value="TEMPPP #{o.id}" action="#{administrationController.sendUserInformation(o.id)}"/> -->
<!--
<h:commandButton value="TEMPPP #{o.id}" action="#{administrationController.sendUserInformation()}">
<f:param name="id" value="#{o.id}"/>
</h:commandButton>
-->
<h:commandButton value="TEMPPP #{o.id}" action="#{administrationController.sendUserInformation(o.id)}" styleClass="buttonGeneral" >
</h:commandButton>
<!--
<h:button value="TEMPPP #{o.id}" outcome="userInformation.xhtml">
<f:param name="id" value="#{o.id}"/>
</h:button>
-->
</h:column>
</h:dataTable>
</h:form>
</ui:define>
</ui:composition>
AdministrationController
package controller;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.faces.context.FacesContext;
import others.MenuBars;
import database.Queries;
import users.User;
public class AdministrationController implements Serializable {
private static final long serialVersionUID = -2151888463865423931L;
private Queries queries = (Queries) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("queries");
private MenuBars menubars = (MenuBars)FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("menuBars");
private List<User> users = new ArrayList<User>();
private List<User> foundUsers = new ArrayList<User>();
private String forename = "";
private String surename = "";
public AdministrationController(){
System.out.println("AdministrationController()");
users = queries.getAllUsers();
}
/*
public void tempUser(ValueChangeEvent event){
System.out.println(event.getNewValue().getClass());
User u = (User) event.getNewValue();
//TODO
System.out.println("idz do informacji o uzytkowniku"+u.name());
}*/
public String getForename() {
return forename;
}
public void setForename(String forename) {
this.forename = forename;
}
public String getSurename() {
return surename;
}
public void setSurename(String surename) {
this.surename = surename;
}
public void find_employee(){
System.out.println("find_employee()");
foundUsers.clear();
for(User u: users){
if(u.getForename().equalsIgnoreCase(getForename()) && u.getSurename().equalsIgnoreCase(getSurename())){
foundUsers.add(u);
}
}
}
public List<User> getFoundUsers() {
return foundUsers;
}
public void setFoundUsers(List<User> foundUsers) {
this.foundUsers = foundUsers;
}
public String sendUserInformation(String id){
System.out.println("sendUserInformation; id = "+id);
menubars.addToMap("id", id);
return "userInformation.xhtml";
}
}
SOLVED!
f:ajax was needed (and probably viewscope)
<h:commandButton action="#{administrationController.sendUserInformation(o.id)}" styleClass="buttonGeneral" value="TEMP #{o.id}">
<f:ajax/>
</h:commandButton>
Assuming that your AdministrationController bean is #RequestScoped (since you haven't specified it's scope), then the data in your <h:dataTable> will be reloaded per every request in the same view. This means, when you select
<h:commandButton value="TEMPPP #{o.id}" action="#{administrationController.sendUserInformation(o.id)}"/>
This will fire a new AdministrationController and the data in the List will be lost, which will break your action since o.id is not available anymore.
To solve this, use a wider scope like #ViewScoped at least.
#ManagedBean
#ViewScoped
public class AdministrationController implements Serializable {
//rest of your code
}
Related
I have problem with InputText. When I try to get the InputText value after clicking the button, the value is null.
When I create the login page, there isn't a problem but using a DataTable does.
package controller;
import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ViewScoped;
import model.Groups;
import model.Student;
import util.DataHolder;
#ManagedBean(name = "edit", eager = true)
#SessionScoped
#RequestScoped
public class EditController implements Serializable {
private static final long serialVersionUID = 1L;
private List<Student> studentList;
private Groups group;
#PostConstruct
public void init() {
this.group = DataHolder.getGroup();
}
public List<Student> getStudentList() {
studentList = group.getStudents();
return studentList;
}
public void saveGrade(Student student) {
System.out.println(student.getName() + " " + student.getSurname() + "grade =" + student.getGrade());
}
public Groups getGroup() {
return group;
}
public void setGroup(Groups group) {
this.group = group;
}
public void setStudentList(List<Student> studentList) {
this.studentList = studentList;
}
}
<?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://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:head>
<title>Edit Page</title>
<link rel="stylesheet"
href="https://cdn.datatables.net/1.10.11/css/jquery.dataTables.min.css"></link>
<script src="https://code.jquery.com/jquery-1.12.0.min.js"></script>
<script
src="https://cdn.datatables.net/1.10.11/js/jquery.dataTables.min.js"></script>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"></link>
<link rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"></link>
<script>
$(document).ready(function() {
$('#example').DataTable();
});
</script>
<h:body>
<div class="container">
<h:dataTable value="#{edit.studentList}" var="student"
styleClass="table table-striped table-bordered" id="example">
<h:column headerText="Student">
<f:facet name="header">
<h:outputLabel>Student</h:outputLabel>
</f:facet>
<h:outputText value="#{edit.studentList.indexOf(student) + 1}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel>Number</h:outputLabel>
</f:facet>
<h:outputText value="#{student.no}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel>Name</h:outputLabel>
</f:facet>
<h:outputText value="#{student.name}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel>Surname</h:outputLabel>
</f:facet>
<h:outputText value="#{student.surname}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputLabel>Grade</h:outputLabel>
</f:facet>
<h:column>
<h:form>
<h:inputText value="#{student.grade}" class="form-control"></h:inputText>
</h:form>
</h:column>
</h:column>
<h:column>
<h:form>
<h:commandButton class="btn btn-danger btn-sm" value="Save"
action="#{edit.saveGrade(student)}" />
</h:form>
</h:column>
<h:column>
<h:form>
<h:commandButton class="btn btn-danger btn-sm" value="Delete"
action="#{edit.deleteStudent(student)}" />
</h:form>
</h:column>
</h:dataTable>
</div>
</h:body>
</html>
I want to get some information about contacts and display them in a table. I used two managed beans named by PersonalContact and BusinessContact and one abstract class named by Contact including firstName, lastName, ID, email and mphone attributes which derives from.Also, one generic class to add beans to an arraylist. I put here just BusinessContact as a bean, business as XHTML and tableBusiness as a table and generic class AddressBook, files of personal is parallel of them.
Inputs getting from screen are assigned to attributes of beans but when the beans go to Arraylist to be added, its content becomes null. Why is that? Is that about scopes?
Here is my bean:
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean
#ViewScoped
public class BusinessContact extends Contact{
private String companyName,workPhone;
public BusinessContact() {}
public BusinessContact(String companyName, String workPhone, String ID, String firstName, String lastName, String email, String mphone) {
super(ID, firstName, lastName, email, mphone);
this.companyName = companyName;
this.workPhone = workPhone;
}
/**
* Creates a new instance of BusinessContact
*/
public String getCompanyName() {
return companyName;
}
public void setCompanyName(String companyName) {
this.companyName = companyName;
}
public String getWorkPhone() {
return workPhone;
}
public void setWorkPhone(String workPhone) {
this.workPhone = workPhone;
}
}
Here is my business.xhtml:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org /TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<h:head>
<title>Contact</title>
</h:head>
<h:body>
<h:form>
<h:panelGrid columns="2">
First Name:
<h:inputText id="firstName" required="true"
requiredMessage="Can not be blank" value="#{businessContact.firstName}">
</h:inputText>
ID:
<h:inputText id="id" required="true"
requiredMessage="Can not be blank" value="#{businessContact.ID}">
</h:inputText>
Last Name:
<h:inputText id="lastName" required="true"
requiredMessage="Can not be blank" value="#{businessContact.lastName}">
</h:inputText>
E-mail:
<h:inputText id="email" required="true"
requiredMessage="Can not be blank" value="#{businessContact.email}">
</h:inputText>
Mobile Phone:
<h:inputText id="mphone" required="true"
requiredMessage="Can not be blank" value="#{businessContact.mphone}">
</h:inputText>
Company Name:
<h:inputText id="companyName" required="true"
requiredMessage="Can not be blank" value="#{businessContact.companyName}">
</h:inputText>
Work Phone:
<h:inputText id="workPhone" required="true"
requiredMessage="Can not be blank" value="#{businessContact.workPhone}">
</h:inputText>
</h:panelGrid>
<h:commandButton value="Add" id="add" action="#{addressBook.add(BusinessContact)}"></h:commandButton>
<h:commandButton value="Delete" id="delete" action="#{addressBook.remove(BusinessContact)}"></h:commandButton>
<h:outputLink id="t" value="tableBusiness.xhtml"> Click see the table</h:outputLink>
<ui:debug hotkey="k" rendered="true"/>
</h:form>
</h:body>
This is my generic class for putting beans to an arraylist:
import java.util.ArrayList;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class AddressBook <T extends Contact> {
private ArrayList<T> list = new ArrayList<T>();
T clas;
public ArrayList<T> getList() {
return list;
}
public void setList(ArrayList<T> list) {
this.list = list;
}
public void add(T obj) {
this.clas=obj;
//System.out.println(obj.getFirstName()+" ");
list.add(obj);
}
public void remove(T obj)
{
list.remove(obj);
}
/**
* Creates a new instance of AddressBook
*/
public AddressBook() {}
}
And lastly, this xhmtl for displaying arraylist in table:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
</h:head>
<h:body>
<h:form>
"#{businessContact.firstName}"
<h:dataTable value="#{addressBook.list}" var="BusinessContact">
<h:column>
<f:facet name="header">
First Name
</f:facet>
<h:outputText value="#{businessContact.firstName}">
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
Last Name
</f:facet>
#{businessContact.lastName}
</h:column>
<h:column>
<f:facet name="header">
Mobile Phone
</f:facet>
#{businessContact.mphone}
</h:column>
<h:column>
<f:facet name="header">
E-mail
</f:facet>
#{businessContact.email}
</h:column>
<h:column>
<f:facet name="header">
Company Name
</f:facet>
#{businessContact.companyName}
</h:column>
<h:column>
<f:facet name="header">
Work Phone
</f:facet>
#{businessContact.workPhone}
</h:column>
</h:dataTable>
</h:form>
</h:body>
</html>
You are naming the var="BusinessContact" but trying to use it as "businessContact"
Change this line
<h:dataTable value="#{addressBook.list}" var="BusinessContact">
to this
<h:dataTable value="#{addressBook.list}" var="businessContact">
I'm learning about JSF and am trying to do a tabbed pane following this tutorial:
Tab manager using Ajax and JSF
I have managed to get the tab switch working. Now I want to include a form defined in another XHTML file as tab for this tabbed pane in which there's a dataTable with a commandButton to delete the selected row, called clientes.xhtml. If I navigate directly to this page then delete button works as expected. But when I include this page within contentForm it shows as expected but delete button doesn't do what is supposed to do, it just refresh the current page but no row is deleted.
This is what I have so far:
welcome.xhtml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns="http://www.w3.org/1999/xhtml"
template="./templates/BasicTemplate.xhtml">
<ui:define name="menu_bar">
<h:form id="formMenu">
<ul id="menu-list">
<li><h:commandLink value="Home">
<f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(0)}" />
</h:commandLink></li>
<li><h:commandLink value="Clientes">
<f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(1)}" />
</h:commandLink></li>
<li><h:commandLink value="Proveedores">
<f:ajax event="click" render=":contentForm" listener="#{tabViewManagedBean.setTabIndex(2)}" />
</h:commandLink></li>
</ul>
</h:form>
</ui:define>
<ui:define name="content">
<h:form id="contentForm">
<h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 0}">
<h1>Hi there!</h1>
<hr />
</h:panelGroup>
<h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 1}">
<ui:include src="clientes.xhtml" />
</h:panelGroup>
<h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 2}">
<ui:include src="proveedores.xhtml" />
</h:panelGroup>
</h:form>
</ui:define>
</ui:composition>
clientes.xhtml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns="http://www.w3.org/1999/xhtml">
<h:form>
<h:dataTable id="dataTable" value="#{clientesManagedBean.listaClientes}" var="cliente">
<h:column>
<f:facet name="header">
<h:outputText value="Id" />
</f:facet>
<h:outputText value="#{cliente.idCliente}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Fecha de ingreso" />
</f:facet>
<h:outputText value="#{cliente.fechaIngreso}">
<f:convertDateTime pattern="dd/MM/yyyy"/>
</h:outputText>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Nombre" />
</f:facet>
<h:outputText value="#{cliente.nombre}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Domicilio" />
</f:facet>
<h:outputText value="#{cliente.domicilio}" />
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Teléfono" />
</f:facet>
<h:outputText value="#{cliente.telefono}" />
</h:column>
<h:column>
<f:facet name="header" />
<h:commandButton image="./resources/css/delete_16.png" action="#{clientesManagedBean.eliminarCliente(cliente)}"/>
</h:column>
</h:dataTable>
</h:form>
</ui:composition>
Edit 1
Here is the ClientesManagedBean code:
ClientesManagedBean.java
import beans.interfaces.IClientesBeanLocal;
import domain.entities.ClienteJpa;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean
#ViewScoped
public class ClientesManagedBean {
#EJB(beanName = "ClientesBeanJpa")
private IClientesBeanLocal clientesBeanLocal;
private List<ClienteJpa> listaClientes;
private ClienteJpa cliente;
#PostConstruct
public void init() {
listaClientes = new ArrayList<>();
listaClientes.addAll(clientesBeanLocal.getTodos());
}
public List<ClienteJpa> getListaClientes() {
return listaClientes;
}
public ClienteJpa getCliente() {
return cliente;
}
public void eliminarCliente(ClienteJpa cliente) {
if(clientesBeanLocal.eliminar(cliente) == IClientesBeanLocal.EXITO) {
listaClientes.remove(cliente);
}
}
}
And ClientesBeanJpa session bean, just in case:
ClientesBeanJpa.java
import beans.interfaces.IClientesBeanLocal;
import domain.entities.ClienteJpa;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
#Stateless(name = "ClientesBeanJpa")
public class ClientesBeanJpa implements IClientesBeanLocal {
#PersistenceContext(unitName = "CursoJ2eePU")
private EntityManager entityManager;
#Override
#TransactionAttribute(TransactionAttributeType.REQUIRED)
public int eliminar(ClienteJpa cliente) {
if(entityManager == null) {
String error = "Error al inyectar EntityManager en la clase " + getClass().getCanonicalName();
throw new ExceptionInInitializerError(error);
} else {
ClienteJpa clienteAEliminar = entityManager.getReference(ClienteJpa.class, cliente.getIdCliente());
entityManager.remove(clienteAEliminar);
return EXITO;
}
}
}
Edit 2
Based on #Luiggi's suggestion I've tested if ClientesManagedBean#eliminar(cliente) method is even called and I've found this out:
If tabIndex property is set to 1 by default, then clientes.xhtml is rendered and it works as expected.
If tabIndex property is set to another value and then navigate to tab 1, then eliminar(cliente) is not even called.
Including TabViewManagedBean code just in case.
TabViewManagedBean.java
import javax.faces.bean.ManagedBean;
import javax.faces.view.ViewScoped;
#ManagedBean
#ViewScoped
public class TabViewManagedBean {
private Integer tabIndex = 0;
/*
* If I set tabIndex to 1 then clientes.xhtml is rendered by default
* and everithing works as expected.
* But if I set this property to 0 and then navigate to tab 1 then it
* behaves as described.
*/
public TabViewManagedBean() {
super();
}
public Integer getTabIndex() {
return tabIndex;
}
public void setTabIndex(Integer tabIndex) {
this.tabIndex = tabIndex;
}
}
The problem is that you're nesting <form>, which is invalid HTML. This can be noted by this code:
welcome.xhtml:
<ui:define name="content">
<h:form id="contentForm">
<!-- code here... -->
<h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 1}">
<!-- including source of clientes.xhtml page -->
<ui:include src="clientes.xhtml" />
</h:panelGroup>
<!-- code here... -->
</h:form>
</ui:define>
And in clientes.xhtml you have:
<h:form>
<h:dataTable id="dataTable" value="#{clientesManagedBean.listaClientes}" var="cliente">
<!-- more code... -->
</h:dataTable>
<h:form>
Which ends in this way:
<h:form id="contentForm">
<!-- code here... -->
<h:panelGroup layout="block" rendered="#{tabViewManagedBean.tabIndex == 1}">
<h:form>
<h:dataTable id="dataTable" value="#{clientesManagedBean.listaClientes}" var="cliente">
<!-- more code... -->
</h:dataTable>
<h:form>
</h:panelGroup>
<!-- code here... -->
</h:form>
Decide where to define the <h:form> to not have nested forms. IMO you should define the <h:form> in the narrowest possible scope, which in this case will be in clientex.xhtml page only (and in the pages to include).
More info:
commandButton/commandLink/ajax action/listener method not invoked or input value not updated (your scenario resembles case 2 of the accepted answer)
I have trouble displaying my property details on the dialog, after generating the table. Results are shown, but the selected row is not shown on dialog. I have taken over the example from primefaces show case.
<!DOCTYPE html>
<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:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>TODO supply a title</title>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
Dear customer!
<li>#{userDataManager.displayHotelTypeChoice(userDataManager.hotelChoice)}
</li>
<li>#{userDataManager.displayPaxChoice(userDataManager.pax)}
</li>
<li>You have chosen to check in : #{userDataManager.displayCheckinDate(userDataManager.checkinDate)}
</li>
<li>You have chosen to check out : #{userDataManager.displayCheckoutDate(userDataManager.checkoutDate)}
</li>
<li>Total Days of Stay : #{userDataManager.countNightsBetween(userDataManager.checkinDate,userDataManager.checkoutDate)}
</li>
<li>Total Nights of Stay : #{userDataManager.nights}
</li>
<br>
</br>
<h:form id="form">
<p:dataTable id="hotels" var="room" value="#{propertyDataTable.searchByHotelType
(userDataManager.hotelChoice, userDataManager.pax)}"
rowKey="#{room.propertyID}"
selection="#{propertyDataTable.selectedProperty}"
selectionMode="single"
resizableColumns="true">
<f:facet name="header">
#{userDataManager.displayHotelTypeChoice(userDataManager.hotelChoice)}<br></br>
Please select only one choice
</f:facet>
<p:column headerText="Property ID" >
#{room.propertyID}
</p:column>
<p:column headerText="Accommodation" >
#{room.accommodation}
</p:column>
<p:column headerText="Pax" >
#{room.pax}
</p:column>
<p:column headerText="Stars" >
#{room.stars}
</p:column>
<p:column headerText="Type" >
#{room.type}
</p:column>
<f:facet name="footer">
In total there are #{propertyDataTable.listSize(propertyDataTable.
searchByHotelType(userDataManager.hotelChoice,
userDataManager.pax))} hotels.
<p:commandButton id="viewButton" value="View" icon="ui-icon-search"
update=":form:display" oncomplete="hotelDialog.show()">
</p:commandButton>
</f:facet>
</p:dataTable>
<p:dialog id="dialog" header="Hotel Detail" widgetVar="hotelDialog" resizable="false"
width="200" showEffect="clip" hideEffect="fold">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<!--<p:graphicImage value="/resources/images/#{propertyDataTable.selectedProperty.type}.jpg"/>-->
<p:graphicImage value="/resources/images/Grand.jpg"/>
</f:facet>
<h:outputText value="Accommodation:" />
<h:outputText value="#{propertyDataTable.selectedProperty.accommodation }" />
<h:outputText value="Feature:" />
<h:outputText value="#{propertyDataTable.selectedProperty.feature}" />
<h:outputText value="Stars:" />
<h:outputText value="#{propertyDataTable.selectedProperty.stars}" />
</h:panelGrid>
</p:dialog>
</h:form>
<br></br>
<br></br>
<h:commandButton value="Book"
action="#{navigationController.showPage()}" >
<f:param name="page" value="book" />
</h:commandButton>
<br></br>
<h:commandButton value="HOME"
action="#{navigationController.showPage()}" >
<f:param name="page" value="home" />
</h:commandButton>
</h:body>
</html>
package dataTable;
import irms.entity.accommodation.Property;
import irms.entity.accommodation.Room;
import irms.session.accommodation.PropertySession;
import irms.session.accommodation.ReservationSession;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
/**
*
* #author Lawrence
*/
#ManagedBean(name = "propertyDataTable")
#ViewScoped
public class PropertyDataTable implements Serializable{
#EJB
private ReservationSession reservationSession;
#EJB
private PropertySession propertySession;
private List<Property> propertyList;
private int choice;
private Property selectedProperty;
private List<Room> list = new ArrayList();
public PropertyDataTable() {
}
public List<Property> getAllRooms() {
return reservationSession.getAllRooms();
}
public List<Property> searchByHotelType(String hotelType, Integer pax) {
this.propertyList = propertySession.searchByHotelType(hotelType, pax);
return propertyList;
}
public int listSize(List<Property> list){
return list.size();
}
public Room getRoom(String propertyID, Integer roomID) {
return propertySession.findRoom(propertyID, roomID);
}
public List<Room> getRoomList(String propertyID){
return propertySession.getRoomList(propertyID);
}
public ReservationSession getReservationSession() {
return reservationSession;
}
public void setReservationSession(ReservationSession reservationSession) {
this.reservationSession = reservationSession;
}
public PropertySession getPropertySession() {
return propertySession;
}
public void setPropertySession(PropertySession propertySession) {
this.propertySession = propertySession;
}
public List<Property> getPropertyList() {
return propertyList;
}
public void setPropertyList(List<Property> propertyList) {
this.propertyList = propertyList;
}
public int getChoice() {
return choice;
}
public void setChoice(int choice) {
this.choice = choice;
}
public Property getSelectedProperty() {
return selectedProperty;
}
public void setSelectedProperty(Property selectedProperty) {
this.selectedProperty = selectedProperty;
}
public List<Room> getList() {
return list;
}
public void setList(List<Room> list) {
this.list = list;
}
}
You Must add ActionListener in your viewButton commandButton
change your xhtml page like this:
<!DOCTYPE html>
<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:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>TODO supply a title</title>
<h:outputStylesheet library="css" name="styles.css" />
</h:head>
<h:body>
Dear customer!
<li>#{userDataManager.displayHotelTypeChoice(userDataManager.hotelChoice)}
</li>
<li>#{userDataManager.displayPaxChoice(userDataManager.pax)}
</li>
<li>You have chosen to check in : #{userDataManager.displayCheckinDate(userDataManager.checkinDate)}
</li>
<li>You have chosen to check out : #{userDataManager.displayCheckoutDate(userDataManager.checkoutDate)}
</li>
<li>Total Days of Stay : #{userDataManager.countNightsBetween(userDataManager.checkinDate,userDataManager.checkoutDate)}
</li>
<li>Total Nights of Stay : #{userDataManager.nights}
</li>
<br>
</br>
<h:form id="form">
<p:dataTable id="hotels" var="room" value="#{propertyDataTable.searchByHotelType
(userDataManager.hotelChoice, userDataManager.pax)}"
rowKey="#{room.propertyID}"
resizableColumns="true">
<f:facet name="header">
#{userDataManager.displayHotelTypeChoice(userDataManager.hotelChoice)}<br></br>
Please select only one choice
</f:facet>
<p:column headerText="Property ID" >
#{room.propertyID}
</p:column>
<p:column headerText="Accommodation" >
#{room.accommodation}
</p:column>
<p:column headerText="Pax" >
#{room.pax}
</p:column>
<p:column headerText="Stars" >
#{room.stars}
</p:column>
<p:column headerText="Type" >
#{room.type}
</p:column>
<f:facet name="footer">
In total there are #{propertyDataTable.listSize(propertyDataTable.
searchByHotelType(userDataManager.hotelChoice,
userDataManager.pax))} hotels.
<p:commandButton id="viewButton" value="View" icon="ui-icon-search"
update=":form:display" oncomplete="hotelDialog.show()">
<f:setPropertyActionListener value="#{room}" target="#{propertyDataTable.selectedProperty}" />
</p:commandButton>
</f:facet>
</p:dataTable>
<p:dialog id="dialog" header="Hotel Detail" widgetVar="hotelDialog" resizable="false"
width="200" showEffect="clip" hideEffect="fold">
<h:panelGrid id="display" columns="2" cellpadding="4">
<f:facet name="header">
<!--<p:graphicImage value="/resources/images/#{propertyDataTable.selectedProperty.type}.jpg"/>-->
<p:graphicImage value="/resources/images/Grand.jpg"/>
</f:facet>
<h:outputText value="Accommodation:" />
<h:outputText value="#{propertyDataTable.selectedProperty.accommodation }" />
<h:outputText value="Feature:" />
<h:outputText value="#{propertyDataTable.selectedProperty.feature}" />
<h:outputText value="Stars:" />
<h:outputText value="#{propertyDataTable.selectedProperty.stars}" />
</h:panelGrid>
</p:dialog>
</h:form>
<br></br>
<br></br>
<h:commandButton value="Book"
action="#{navigationController.showPage()}" >
<f:param name="page" value="book" />
</h:commandButton>
<br></br>
<h:commandButton value="HOME"
action="#{navigationController.showPage()}" >
<f:param name="page" value="home" />
</h:commandButton>
</h:body>
</html>
I have a problem displaying validation errors that are triggered by ui components which are
nested inside a dataTable.
Here is the xhtml page, which contains a form with a static upper part, where an address can be entered.
Below that it shows order items where users can enter amounts of items they would like to order.
These items are being retrieved from a database table and are diplayed inside a dataTable.
<!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">
<ui:composition template="../templates/_standard.xhtml">
<ui:define name="pageHeadline">
#{msg['supplies.module_headline']}
</ui:define>
<ui:define name="pageContent">
<h:form id="supplies" styleClass="editForm" rendered="#{!suppliesHandler.sent}">
<h:panelGrid
columns="2"
columnClasses="tdLabel,tdValue"
rowClasses="row"
styleClass="leftPane"
>
<!-- row 1 -->
#{msg['supplies.account']}:
<h:panelGroup>
<h:inputText id="account" value="#{supply.contact.account}" tabindex="1" styleClass="text"/>
<h:message for="account" styleClass="error"/>
</h:panelGroup>
<!-- row 2 -->
#{msg['supplies.company']}:
<h:panelGroup>
<h:inputText id="company" value="#{supply.contact.company}" tabindex="2" styleClass="text"/>
<h:message for="company" styleClass="error"/>
</h:panelGroup>
<!-- row 3 -->
#{msg['supplies.street']}:
<h:panelGroup>
<h:inputText id="street" value="#{supply.contact.street}" tabindex="3" styleClass="text"/>
<h:message for="street" styleClass="error"/>
</h:panelGroup>
<!-- row 4 -->
#{msg['supplies.postcode']}:
<h:panelGroup>
<h:inputText id="postcode" value="#{supply.contact.postcode}" tabindex="4" styleClass="text"/>
<h:message for="postcode" styleClass="error"/>
</h:panelGroup>
<!-- row 5 -->
#{msg['supplies.city']}:
<h:panelGroup>
<h:inputText id="city" value="#{supply.contact.city}" tabindex="5" styleClass="text"/>
<h:message for="city" styleClass="error"/>
</h:panelGroup>
</h:panelGrid>
<h:panelGrid
columns="2"
columnClasses="tdLabel,tdValue"
rowClasses="row"
styleClass="rightPane"
>
<!-- row 2 -->
#{msg['supplies.contact']}:
<h:panelGroup>
<h:inputText id="contact" value="#{supply.contact.contact}" tabindex="6" styleClass="text"/>
<h:message for="contact" styleClass="error"/>
</h:panelGroup>
<!-- row 3 -->
#{msg['supplies.phone']}:
<h:panelGroup>
<h:inputText id="phone" value="#{supply.contact.phone}" tabindex="7" styleClass="text"/>
<h:message for="phone" styleClass="error"/>
</h:panelGroup>
<!-- row 4 -->
#{msg['supplies.email']}:
<h:panelGroup>
<h:inputText id="email" value="#{supply.contact.email}" tabindex="8" styleClass="text">
<f:validator validatorId="com.abc.myproduct.be.ui.validator" />
</h:inputText>
<h:message for="email" styleClass="error"/>
</h:panelGroup>
<!-- row 5 -->
#{msg['supplies.fax']}:
<h:panelGroup>
<h:inputText id="fax" value="#{supply.contact.fax}" tabindex="9" styleClass="text"/>
<h:message for="fax" styleClass="error"/>
</h:panelGroup>
</h:panelGrid>
<div class="spacer"></div>
<h:dataTable id="items"
styleClass="listing_large"
value="#{supply.supplyItems}"
headerClass="heading"
var="item">
<h:column>
<f:facet name="header">
#{msg['supplies.id']}
</f:facet>
<h:outputText value="#{item.supply_id}" />
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.amount']}
</f:facet>
<h:inputText value="#{item.amount}" id="amount" styleClass="text" size="3" maxlength="3" style="width:50px"/>
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.description']}
</f:facet>
<h:outputText value="#{item.description}" />
</h:column>
</h:dataTable>
<div><br/>
<h:messages globalOnly="true" layout="table" styleClass="error"/>
</div>
<h:panelGrid
columns="1"
columnClasses="tdLabel,tdValue"
rowClasses="row">
<!-- row 2 -->
<h:panelGroup>
<h:commandButton value="#{msg['general.submit']}" action="#{suppliesHandler.submitMessage}" styleClass="button"/>
</h:panelGroup>
</h:panelGrid>
</h:form>
<h:messages globalOnly="true" layout="table" rendered="#{suppliesHandler.sent}"/>
</ui:define>
</ui:composition>
</html>
Validation for the address part of the form works perfect.
Only the messages for this part of the form are not being displayed:
<h:dataTable id="items"
styleClass="listing_large"
value="#{supply.supplyItems}"
headerClass="heading"
var="item">
<h:column>
<f:facet name="header">
#{msg['supplies.id']}
</f:facet>
<h:outputText value="#{item.supply_id}" />
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.amount']}
</f:facet>
<h:inputText value="#{item.amount}" id="amount" styleClass="text" size="3" maxlength="3" style="width:50px"/>
</h:column>
<h:column>
<f:facet name="header">
#{msg['supplies.description']}
</f:facet>
<h:outputText value="#{item.description}" />
</h:column>
</h:dataTable>
Validation is being carried out through BeanValidation:
public class SupplyItem implements Serializable {
private static final long serialVersionUID = 1L;
#Id
private long supply_id;
private String description;
private int orderNo;
#Transient
#Max(value=200)
private int amount;
/*
* constructor
*/
public SupplyItem() {
super();
}
public long getSupply_id() {
return supply_id;
}
public void setSupply_id(long supply_id) {
this.supply_id = supply_id;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public int getOrderNo() {
return orderNo;
}
public void setOrderNo(int orderNo) {
this.orderNo = orderNo;
}
public int getAmount() {
return amount;
}
public void setAmount(int amount) {
this.amount = amount;
}
}
It gets actually being validated, however the messages are not being displayed...
12:29:45,860 Information [javax.enterprise.resource.webcontainer.jsf.renderkit] (http--127.0.0.1-8080-2) WARNUNG: FacesMessage(s) wurde(n) in die Warteschlange gestellt, aber möglicherweise nicht angezeigt.
sourceId=supplies:items:0:amount[severity=(ERROR 2), summary=(Allowed maximum is 200), detail=(Allowed maximum is 200)]
sourceId=supplies:items:1:amount[severity=(ERROR 2), summary=(supplies:items:1:amount: 'a' must be a number consisting of one or more digits.), detail=(supplies:items:1:amount: 'a' must be a number between -2147483648 and 2147483647 Example: 9346)]
Trying to set the id of the input field dynamically in conjunction with a
h:message for="" did not work,displaying it through h:messages globalOnly="true" neither.
Any help would be highly appreciated.
You have not put a <h:message> for the input field anywhere in the datatable. You need to put a
<h:message for="amount" />
somewhere in the datatable exactly there where you'd like to display them.
The <h:messages globalOnly="true"> only displays messages with a null client ID, so that surely won't work at all for messages with a non-null client ID. You'd need to remove globalOnly="true" in order to display messages which are not shown anywhere else.