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)
Related
I have a button outside the datatable form which function is to delete the selected row, but the problem is that it returns an empty value of that row in the backing bean, the update of the growl message is done correctly and the action is called too.
However when putting the button inside the form it works fine, but I need it to be in the toolbar which is outside the form.
This is my xhtml code:
<ui:define name="content">
<div class="row">
<p:toolbar id="tb">
<f:facet name="left">
<p:inputText style="margin-right:10px" placeholder="Rechercher..." />
<p:commandButton icon="fa fa-search" />
</f:facet>
<f:facet name="right">
<p:commandButton onclick="PF('analyseForm').show();" icon="fa fa-plus" />
<p:commandButton icon="fa fa-file-pdf-o" />
<p:commandButton process="#this,:form:anaDT" update=":form" action="#{personel.removeSelectedAnalyse}" icon="fa fa-trash-o" />
<!-- this button does the update and runs the action but returns a null value of the selected row-->
</f:facet>
</p:toolbar>
</div>
<div class="row">
<h:form id="form">
<p:growl id="msgs" />
<p:dataTable style="font-size:12px;" id="anaDT" scrollable="true" scrollWidth="100%" var="ana" value="#{personel.analyses}" paginator="true" selectionMode="single" selection="#{personel.selectedAnalyse}" paginatorPosition="bottom" rowKey="#{ana.idAnalyse}"
rows="10">
<!-- columns here -->
<f:facet name="footer">
<!-- this button works fine -->
<p:commandButton class="btn btn-default" process="form:anaDT" update="form" ajax="true" icon="fa fa-trash-o" action="#{personel.removeSelectedAnalyse}" />
</f:facet>
</p:dataTable>
</h:form>
</div>
<p:sticky target=":tb" margin="50" />
</ui:define>
</ui:composition>
Command button outside of a form can not be used to submit a form. If you want to achieve the functionality you desire, one way is to
Have a p:remoteCommand inside the form and bind it to the backing bean method personel.removeSelectedAnalyse and have update="#form"
Invoke the remoteCommand from the command button from the tool bar using onclick attribute and the remoteCommand submits the form. Now the backing bean will have the submitted values from the form so you can do the necessary processing and the form will be updated after the Ajax request completes.
Remote Command showcase: https://www.primefaces.org/showcase/ui/ajax/remoteCommand.xhtml
I've changed the rowKey to the entity type, assigning an unique id to the form. There is no need to process the form at the p:commandButton click. I place this button into a <h:form>. Command components always must be there. The entity selection done at row click. When you click on the button it uses the preset entity to remove from the List. Just the rerendering of the <p:dataTable> is needed. And I move the controller into the javax.faces.view.ViewScope. PrimeFaces component use ajax by default so the controllers must be at least as wide scope as view.
The facelet:
?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:p="http://primefaces.org/ui"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<div class="row" >
<h:form id="toolbarForm">
<p:toolbar id="tb">
<f:facet name="left">
<p:commandButton value="Delete selected User" process="#this" update="myForm" actionListener="#{myBean.deleteUser}"/>
</f:facet>
</p:toolbar>
</h:form>
</div>
<h:form id="myForm">
<p:dataTable id="usersTable" value="#{myBean.users}" var="user" selectionMode="single" selection="#{myBean.selectedUser}" rowKey="#{user}">
<p:column>
<f:facet name="header">ID</f:facet>
#{user.id}
</p:column>
<p:column>
<f:facet name="header">First name</f:facet>
#{user.firstName}
</p:column>
<p:column>
<f:facet name="header">Last name</f:facet>
#{user.lastName}
</p:column>
</p:dataTable>
</h:form>
</h:body>
</html>
The controller:
package x;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.inject.Named;
import javax.faces.view.ViewScoped;
import lombok.Data;
#Data
#Named( value = "myBean" )
#ViewScoped
public class MyBean implements Serializable
{
private List<User> users;
private User selectedUser;
public MyBean()
{
users = new ArrayList<>();
users.add( new User( 1, "First1", "Last1" ) );
users.add( new User( 2, "First2", "Last2" ) );
users.add( new User( 3, "First3", "Last3" ) );
users.add( new User( 4, "First4", "Last4" ) );
users.add( new User( 5, "First5", "Last5" ) );
}
#PostConstruct
public void init()
{
System.out.println( "MyBean.init() called" );
}
public void deleteUser()
{
if ( selectedUser == null )
System.out.println( "Selected User is null" );
else
System.out.println( "The ID of the User to remove: " + Integer.toString( selectedUser.getId() ) );
boolean bn = users.remove( selectedUser );
}
}
The User class:
package x;
import lombok.Data;
#Data
public class User
{
private int id;
private String firstName;
private String lastName;
public User( int id_, String firstName_, String lastName_ )
{
id = id_;
firstName = firstName_;
lastName = lastName_;
}
}
The source contains lombok annotations to avoid boilerplate coding (getter/setter methods)
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 try to get the information about the clicked button in a <p:datalist>, but it doesn't work.
My View:
<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="head">
<title>Hash Generator</title>
</ui:define>
<ui:define name="content">
<h:form id="hashForm">
<p:dataList id="hashList" value="#{hashGeneratorBean.hashList}" var="entry" rowIndexVar="idx" itemType="none">
<p:column>
<h:outputText value="#{idx + 1}" />
<h:inputText value="#{entry.clearText}" />
<h:inputText value="#{entry.hashedText}" readonly="true" disabled="true" size="#{entry.hashedText.length() + 15}"/>
<p:commandButton id="addRow" actionListener="#{hashGeneratorBean.addRow}" icon="ui-icon-plus" title="Icon Only" update="hashList">
<f:setPropertyActionListener value="#{entry}" target="#{hashGeneratorBean.selectedRow}" />
</p:commandButton>
<p:commandButton id="debugBtn" icon="ui-icon-disc" title="Icon Only" update=":hashForm:display" oncomplete="PF('dlg').show()">
<f:setPropertyActionListener value="#{entry}" target="#{hashGeneratorBean.selectedRow}" />
</p:commandButton>
</p:column>
</p:dataList>
<p:commandButton actionListener="#{hashGeneratorBean.hash}" value="Generate Hashes" update="hashList" />
<p:dialog modal="true" widgetVar="dlg">
<h:panelGrid id="display" columns="2">
<f:facet name="header">
<h:outputText value="#{hashGeneratorBean.selectedRow.clearText}" />
</f:facet>
<h:outputText value="#{hashGeneratorBean.selectedRow.hashedText}" />
</h:panelGrid>
</p:dialog>
</h:form>
</ui:define>
</ui:composition>
My Controller:
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import com.google.common.base.Charsets;
import com.google.common.hash.Hashing;
#ManagedBean
#ViewScoped
public class HashGeneratorBean {
private List<HashDTO> hashList = new ArrayList<HashDTO>();
private HashDTO selectedRow = new HashDTO();
#PostConstruct
public void init() {
hashList.add(new HashDTO());
}
public void addRow(ActionEvent ae){
hashList.add(new HashDTO());
}
public void hash(ActionEvent ae){
for (HashDTO entry : hashList){
entry.setHashedText(generateHash(entry.getClearText()));
}
}
/**
* Hashes the given password with SHA-256
* #param password
* #return passwordHash
*/
public static String generateHash(String password) {
return Hashing.sha256().hashString(password, Charsets.UTF_8).toString();
}
public List<HashDTO> getHashList() {
return hashList;
}
public void setHashList(List<HashDTO> hashList) {
this.hashList = hashList;
}"
public HashDTO getSelectedRow() {
return selectedRow;
}
public void setSelectedRow(HashDTO selectedRow) {
this.selectedRow = selectedRow;
}
}
If I click the "debugBtn"-button the dialog popups up and shows the correct information about the row. But If I click the "addRow"-button the data in the managed-bean isn't filled correct. The selectedRow-property allways stores the last added row from the hashList-property.
I found the solution.
The PropertyActionListener is called after the ActionListener.
the Solution is to use "Action" or register the the ActionListener with and a Extended Action Listener
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'm having a problem when I include dynamically a page with <ui:include>, the action and actionlistener associated with the <p:commandButton> component is not being invoked.
I've tried to remove the tag <h:form> from the included page but the problem persists.What can I do to solve this problem?
The source code:
hello.xhtm (Main Page)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<f:view>
<h:head>
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<f:view contentType="text/html" />
</h:head>
<h:body>
<h:form id="helloForm">
<p:growl id="messages" />
<p:panelGrid id="panelGridPrincipal" styleClass="panelGridPrincipal">
<p:row>
<p:column colspan="2">
<div style="width: 100%; height: 25px; padding-left: 230px;">
<p:commandButton id="botao1" value="Bookmark" styleClass="button"/>
<p:commandButton id="botao2" value="Bookmark2" styleClass="button"
actionListener="#{mainBean.renderMenuVendas}" update="panel" >
<f:setPropertyActionListener value="2" target="#{mainBean.menuType}" />
</p:commandButton>
</div>
</p:column>
</p:row>
<p:row>
<p:column id="column2" style="width:200px;background-color: #5A5858;">
<h:panelGrid id="panel" styleClass="panelGridMenu" columns="1">
<p:menu id="dynamicMenu" model="#{mainBean.sideMenu}" rendered="#{mainBean.showMenuVendas}" style="width:189px;margin-right:100%;"/>
<p:spacer width="50px" height="700px" />
</h:panelGrid>
</p:column>
<p:column style="background-color: white">
<p:panelGrid style="border:1px;">
<p:row>
<p:column>
<p:outputPanel id="outputPanelConteudo">
<ui:include src="#{mainBean.paginaAtual}" />
</p:outputPanel>
</p:column>
</p:row>
<p:row/>
</p:panelGrid>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</h:body>
</f:view>
</html>
pagina1.xhtml (Included Page)
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<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:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<p:dataTable id="avioes" var="aviao" value="#{listaAvioesBean.aviao}"
rowKey="#{aviao.numeroSerie}"
selection="#{listaAvioesBean.selectedAviao}" selectionMode="single"
style="width:500px">
<p:column style="width:75px">
<f:facet name="header">
<h:outputText value="Numero de Serie" />
</f:facet>
<h:outputText value="#{aviao.numeroSerie}" />
</p:column>
<p:column style="width:100px">
<f:facet name="header">
<h:outputText value="Marca" />
</f:facet>
<h:outputText value="#{aviao.marca}" />
</p:column>
<p:column style="width:75px">
<f:facet name="header">
<h:outputText value="Modelo" />
</f:facet>
<h:outputText value="#{aviao.modelo}" />
</p:column>
<p:column style="width:75px">
<p:commandButton id="insertAviao" value="Inserir" title="Visualizar">
<f:setPropertyActionListener value="#{aviao}"
target="#{listaAvioesBean.selectedAviao}" />
</p:commandButton>
<!--THESE ACTION DOESN'T CALL THE BEAN METHOD!!! -->
<p:commandButton id="removerAviao" style="width:50px" value="P"
title="Deletar" action="#{listaAvioesBean.removerAviao}"
update=":helloForm:outputPanelConteudo">
<f:setPropertyActionListener value="#{aviao}"
target="#{listaAvioesBean.selectedAviao}" />
</p:commandButton>
</p:column>
</p:dataTable>
</ui:composition>
Managed bean (ListaAvioesBean.java)
package br.com.erp.beans;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import br.com.erp.object.Aviao;
#ManagedBean(name="listaAvioesBean")
#ViewScoped
public class ListaAvioesBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 8076960891132613195L;
private Aviao selectedAviao;
private List<Aviao> aviao;
public ListaAvioesBean(){
aviao = new ArrayList<Aviao>();
System.out.println("ListaAvioesBean Criado!");
}
#PostConstruct
public void init(){
System.out.println("Iniciando o bean!");
populateListAvioes();
}
public void executa(){
System.out.println("Executou");
}
private void populateListAvioes(){
Aviao av1 = new Aviao();
av1.setMarca("Marca1");
av1.setModelo("M1");
av1.setNumeroSerie("1234");
aviao.add(av1);
av1 = new Aviao();
av1.setMarca("Marca2");
av1.setModelo("M2");
av1.setNumeroSerie("1111");
aviao.add(av1);
av1 = new Aviao();
av1.setMarca("Marca3");
av1.setModelo("M3");
av1.setNumeroSerie("4321");
aviao.add(av1);
}
public Aviao getSelectedAviao() {
return selectedAviao;
}
public void setSelectedAviao(Aviao selectedAviao) {
this.selectedAviao = selectedAviao;
}
public List<Aviao> getAviao() {
return aviao;
}
public void setAviao(List<Aviao> aviao) {
this.aviao = aviao;
}
public void removerAviao(){
boolean removeu = aviao.remove(selectedAviao);
if(removeu)
System.out.println("Avião removido com sucesso");
}
public void executa(ActionEvent e){
System.out.println();
}
}