<h:commandButton> action is not invoked - jsf

I've got a bit of a problem. Basically I have a page with a form containing an input text field, a search button and a ui:repeat structure that displays the results of the search using more input text fields and a couple of other buttons (the idea is to list all search hits and allow the user to edit them directly from the same page). Now, the search and the display part works well - it does what it's supposed to. However, when I try to click on one of the buttons that are displayed in the ui:repeat section, the action isn't invoked.
When I press the search button (Pretraga in code) a function is called in the Kupac bean which then gets the results from the database and places them into a list and finally redirects back to the same page (from my understanding this will load the page again) and lists the results using the ui:repeat component. But as I said, when I press the other buttons (Izmeni and Glavna in code) they do nothing. Kupac bean is #RequestScoped and I already tried changing it to #ViewScoped, however this only made it worse by having the search not work as well (i.e. it will display nothing).
Here's the JSF page code:
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Pregled kupaca</title>
</h:head>
<h:body>
<h3 align="center">Pregled kupaca</h3>
<h:form>
<table align="center">
<tr>
<td align="center" colspan="2"><h:link outcome="pocetna.xhtml">Pocetna</h:link></td>
</tr>
<tr>
<td>Firma</td>
<td><h:inputText value="#{kupac.naziv_firme}"/></td>
</tr>
<tr>
<td align="center" colspan="2">
<h:commandButton action="#{kupac.listKupci()}" value="Pretraga">
</h:commandButton>
</td>
</tr>
</table>
<br/>
<ui:repeat value="#{kupac.zeljeni_kupci}" var="kupac">
<table align="center" border="1">
<tr>
<td>Ime i prezime</td>
<td><h:inputText
required="true"
requiredMessage="Niste uneli ime i prezime!"
value="#{kupac.ime_prezime}"/></td>
</tr>
<tr>
<td>Adresa</td>
<td><h:inputText
required="true"
requiredMessage="Niste uneli adresu!"
value="#{kupac.adresa}"/></td>
</tr>
<tr>
<td>Naziv firme</td>
<td><h:inputText
required="true"
requiredMessage="Niste uneli naziv firme!"
value="#{kupac.naziv_firme}"/></td>
</tr>
<tr>
<td>Adresa firme</td>
<td><h:inputText
required="true"
requiredMessage="Niste uneli adresu firme!"
value="#{kupac.adresa_firme}"/></td>
</tr>
<tr>
<td>Br. telefona</td>
<td><h:inputText
required="true"
requiredMessage="Niste uneli broj telefona!"
value="#{kupac.br_tel}"/></td>
</tr>
<tr>
<td>
<h:commandButton value="Izmeni" action="#{kupac.izmenaKupca()}"/>
</td>
<td><h:commandButton action="#{kupac.test()}" value="Glavna"/></td>
</tr>
</table>
<br/><br/>
</ui:repeat>
</h:form>
</h:body>
</html>
and here's the full bean code in Java:
package beans;
import exceptions.DBException;
import java.io.Serializable;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.bean.ViewScoped;
import util.Database;
#ManagedBean
#RequestScoped
public class Kupac implements Serializable {
private int id_kupac;
private String ime_prezime;
private String adresa;
private String naziv_firme;
private String adresa_firme;
private String br_tel;
private List<Kupac> svi_kupci;
private List<Kupac> zeljeni_kupci;
public void init() {
listKupci();
}
public void poruka() {
System.out.println("ID "+id_kupac);
}
public String test() {
return "pocetna";
}
public String izmenaKupca() throws DBException {
Kupac kupac = new Kupac();
Database db = Database.getInstance();
kupac.setId_kupac(id_kupac);
kupac.setIme_prezime(ime_prezime);
kupac.setAdresa(adresa);
kupac.setNaziv_firme(naziv_firme);
kupac.setAdresa_firme(adresa_firme);
kupac.setBr_tel(br_tel);
try {
db.updateKupac(kupac);
} catch (DBException ex) {
return "error";
}
return "pregled_kupaca";
}
public String unosKupca() throws DBException {
Kupac kupac = new Kupac();
Database db = Database.getInstance();
kupac.setIme_prezime(ime_prezime);
kupac.setAdresa(adresa);
kupac.setNaziv_firme(naziv_firme);
kupac.setAdresa_firme(adresa_firme);
kupac.setBr_tel(br_tel);
try {
db.insertKupac(kupac);
} catch (DBException ex) {
return "error";
}
return "pocetna";
}
public String listKupci() {
Database db = Database.getInstance();
zeljeni_kupci = new LinkedList<Kupac>();
try {
svi_kupci = db.listKupci();
for (Kupac k : svi_kupci) {
if (k.naziv_firme.equals(naziv_firme) || "".equals(naziv_firme)) {
zeljeni_kupci.add(k);
}
}
} catch (DBException ex) {
return "error";
}
return "pregled_kupaca";
}
public List<Kupac> getZeljeni_kupci() {
return zeljeni_kupci;
}
public void setZeljeni_kupci(List<Kupac> zeljeni_kupci) {
this.zeljeni_kupci = zeljeni_kupci;
}
public List<Kupac> getSvi_kupci() {
return svi_kupci;
}
public void setSvi_kupci(List<Kupac> svi_kupci) {
this.svi_kupci = svi_kupci;
}
public int getId_kupac() {
return id_kupac;
}
public void setId_kupac(int id_kupac) {
this.id_kupac = id_kupac;
}
public String getIme_prezime() {
return ime_prezime;
}
public void setIme_prezime(String ime_prezime) {
this.ime_prezime = ime_prezime;
}
public String getAdresa() {
return adresa;
}
public void setAdresa(String adresa) {
this.adresa = adresa;
}
public String getNaziv_firme() {
return naziv_firme;
}
public void setNaziv_firme(String naziv_firme) {
this.naziv_firme = naziv_firme;
}
public String getAdresa_firme() {
return adresa_firme;
}
public void setAdresa_firme(String adresa_firme) {
this.adresa_firme = adresa_firme;
}
public String getBr_tel() {
return br_tel;
}
public void setBr_tel(String br_tel) {
this.br_tel = br_tel;
}
/**
* Creates a new instance of Kupac
*/
public Kupac() {
}
}
I'm using JSF 2.2 on a GlassFish 4.0 server using Netbeans 7 IDE.
Sorry for the long post and the fact that this question has now been asked several times, but I haven't managed to fix it for 2 hrs now and would appreciate any help. Cheers!

Related

BootsFaces selectMultiMenu not rendering with ajax

i am using a selectMultiMenu from bootsFaces, the initial values are showed perfectly, but after rendered, with the new values the combo doesnt open, if I check the source code in my browser it shows that the bean loeaded the values correctly. It only happens with this bootsFaces's element, the rest of my project with jsf render with no problems with ajax.
Any clue? Thanks!
<h:form id="form-Principal">
<h:panelGroup id="panel-Principal" layout="block" >
<div class="col-md-12">
<div class="col-md-1">
<label for="servicio" class="control-label">Servicio:</label>
</div>
<div class="col-md-2">
<h:selectOneMenu disabled="#{empty testops.ambiente}" id="servicio" class="combobox form-control" value="#{testops.servicio}" >
<f:selectItem itemValue="" itemLabel="Seleccione..."/>
<f:selectItems value="#{testops.listServicios}" />
<f:ajax event="change" listener="#{testops.obtenerOperaciones}" render="cboperacion" execute="#this"></f:ajax>
</h:selectOneMenu>
<h:message for="servicio" class="error"/>
</div>
<div class="col-md-1">
<label for="operacion" class="control-label">Operación:</label>
</div>
<div class="col-md-2">
<b:selectMultiMenu id="cboperacion" value="#{testops.operacion}" nonSelectedText="Seleccione...">
<f:selectItems value="#{testops.operaciones}"/>
</b:selectMultiMenu>
</div>
<div class="col-md-1">
</div>
<div class="col-md-1">
<f:ajax render=":salida form-Principal:panel-Principal" execute="#form" onevent="loading">
<h:commandLink class="btn btn-danger boton_rojo pull-right" value="Ejecutar" action="#{testops.ejecutarOperaciones()}"></h:commandLink>
</f:ajax>
</div>
</div>
</h:panelGroup>
</h:form>enter code here
Onload:
After rendering, it has diffent values, but combo is not display.
I've tried to reproduce your bug without success. Or rather: the code works as intended. The <b:selectMultMenu> is updated with the new values.
[meta] I know this isn't an answer (yet)... I just chose the answer because it's the only way to include source code. [/meta]
So I suggest you
copy me example code below into your project and see if it works
or you send me a "reproducer", i.e. a tiny but complete project showing the problem. For instance, you could upload a Maven project to GitHub. Please reduce the reproduces as much as possible. For instance, I need to be able to run it without configuring a database.
Here's the sourcecode I used to reproduce your bug:
As a basis, I used our showcase.
I copied your JSF code snippet into the empty.xhtml.
I created a JSF bean as follows:
package de.beyondjava.jsf.sample.carshop;
import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class Testops {
private String ambiente = "que";
private List<String> listServicios = new ArrayList<>();
private String operacion;
private List<String> operaciones = new ArrayList<>();
private String servicio;
{
listServicios.add("Servicio 1");
listServicios.add("Servicio 2");
shuffleOperaciones();
}
public void ejecutarOperaciones(Object o) {
}
public String getAmbiente() {
return ambiente;
}
public List<String> getListServicios() {
return listServicios;
}
public String getOperacion() {
return operacion;
}
public List<String> getOperaciones() {
return operaciones;
}
public String getServicio() {
return servicio;
}
public void obtenerOperaciones(Object o) {
shuffleOperaciones();
}
public void setAmbiente(String ambiente) {
this.ambiente = ambiente;
}
public void setListServicios(List<String> listServicios) {
this.listServicios = listServicios;
}
public void setOperacion(String operacion) {
this.operacion = operacion;
}
public void setOperaciones(List<String> operaciones) {
this.operaciones = operaciones;
}
public void setServicio(String servicio) {
this.servicio = servicio;
}
private void shuffleOperaciones() {
operaciones = new ArrayList<>();
for (int i = 0; i < 4; i++) {
operaciones.add("opción " + Math.ceil(Math.random()*1000));
}
}
}
When I chose one of the options of the first combobox, the <b:selectMultiMenu> is updated with the new (random) values.

After form submission , using java ee and jsf 2,2, my backing bean properties are still null

Basically , in the input.xhtml there is a form which takes a username and password and if they are equal to a specific value(doesn't matter the value) the program should print a message in the browser, but this doesn't happen. To make sure of the problem i added 2 lines of "System.out.println(...)" where i print the value of the property and what i found out is that the properties are still null even after i submit. So after i click send in the console is written "null null". Any help is appreciated!
This is the UserBean class (backing bean)
package bean;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean
#SessionScoped
public class UserBean implements Serializable{
/**
*
*/
private static final long serialVersionUID = 1L;
private String name;
private String password;
private String output_message;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String go(){
output_message = "";
if(name == null && password == null){
output_message += "Both fields cannot be empty!";
}else if(name == "name" && password == "pass"){
output_message += "Success!";
}else{
output_message += "Data is wrong!";
}
System.out.println(name);
System.out.println(password);
return output_message;
}
public String getOutput_message() {
return output_message;
}
public void setOutput_message(String output_message) {
this.output_message = output_message;
}
public String ret(String r){
return r;
}
}
This is the input.xhtml file, that contains the form that will submit the data to the bean. (Ignore the url to template.xhtml, it's just a parent template that has a header and a footer other than the mid-content that input.xhtml defines)
<!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://xmlns.jcp.org/jsf/facelets"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite/myComponent">
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="content">
<style type="text/css">
#form1{
position: absolute;
top: 20%;
left:40%;
border: 1px solid black;
background-color: orange;
}
td{
padding-top:10px;
}
input[type="text"]{
backgorund-color:blue;
}
</style>
<form id="form1" method="post">
<table columns="2">
<tr>
<td><span>Emri:</span></td>
<td><input type="text" id="emri" value="#{userBean.name}"/></td>
</tr>
<tr>
<td><span>Password:</span></td>
<td><input type="password" id="pass" value="#{userBean.password}"/></td>
</tr>
<tr>
<td colspan="2" align="center"><button type="submit" onclick="#{userBean.go()}">Send</button></td>
</tr>
</table>
</form>
<p>#{user.output_message}</p>
</ui:define>
</ui:composition>
</html>
The problem caused by the button html tag. Don't use HTML buttons or anchors if you want to use the JSF mechanism. Instead use (button/link) components to submit the page. Define the navigation rules ot the userBean.go should pass back the next page name.
I just solved this. the problem was with the input tag, the value attribute does not represent the value written in the textbox is just some kind of a default value or somekind of a pre-value. Anyway instead of input and form tags i used and which worked out fine
h is a namespace with url xmlns:h="http://xmlns.jcp.org/jsf/html"

jsp code to upload jgp files and save in mysql db

This is my servlet code
package classes;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
#WebServlet("/FileUploadDBServlet")
#MultipartConfig(maxFileSize = 16177215) // upload file's size up to 16MB
public class FileUploadDBServlet extends HttpServlet {
// database connection settings
private String dbURL = "jdbc:mysql://localhost:3306/studreg";
private String dbUser = "root";
private String dbPass = "";
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// gets values of text fields
String matric = request.getParameter("matric");
//String lastName = request.getParameter("lastName");
InputStream inputStream = null; // input stream of the upload file
// obtains the upload file part in this multipart request
Part filePart = request.getPart("photo");
if (filePart != null) {
// prints out some information for debugging
System.out.println(filePart.getName());
System.out.println(filePart.getSize());
System.out.println(filePart.getContentType());
// obtains input stream of the upload file
inputStream = filePart.getInputStream();
}
Connection conn = null; // connection to the database
String message = null; // message will be sent back to client
try {
// connects to the database
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
conn = DriverManager.getConnection(dbURL, dbUser, dbPass);
// constructs SQL statement
String sql = "INSERT INTO contacts (matric, photo) values (?,?)";
PreparedStatement statement = conn.prepareStatement(sql);
statement.setString(1, matric);
//statement.setString(2, lastName);
if (inputStream != null) {
// fetches input stream of the upload file for the blob column
statement.setBlob(2, inputStream);
//statement.setBlob(3, inputStream);
}
// sends the statement to the database server
int row = statement.executeUpdate();
if (row > 0) {
message = "File uploaded and saved for transcript processing";
}
} catch (SQLException ex) {
message = "ERROR: " + ex.getMessage();
ex.printStackTrace();
} finally {
if (conn != null) {
// closes the database connection
try {
conn.close();
} catch (SQLException ex) {
ex.printStackTrace();
}
}
// sets the message in request scope
request.setAttribute("Message", message);
// forwards to the message page
getServletContext().getRequestDispatcher("/message.jsp").forward(request, response);
}
}
}
This is my jsp code
<%# page contentType="text/html; charset=iso-8859-1" language="java" import="java.sql.*" errorPage="" %>
<%# page import ="java.sql.*" %>
<%#page import="classes.DbConn2"%>
<%#page import="classes.FileUploadDBServlet"%>
<!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">
<head>
<form method ="post" action ="receipt.jsp" name="form1">
<p>
<input type="hidden" name="matric" value="<%=matric %>">
<td colspan="2"> <input name="invoiceno" type="hidden" value="<%=invoiceno%>" />
<input type="submit" value="Print Payment Receipt">
</p>
<p> </p>
</form>
<left>
<p>Click here to print <a target="_blank "href="http://www.collegesch.com/reg/receipt.jsp?matric=<%=matric%>&invoiceno=<%=invoiceno%>">Receipt</a>
<h1 align="left">File Upload for Transcript Request</h1>
<form method="post" action="FileUploadDBServlet" name="form2" enctype="multipart/form-data">
<table width="759" border="0">
<td colspan="2"> <input name="matric" type="hidden" value="<%=matric%>" />
<tr>
<td><p>Picture( jpeg, 450X500): </p>
</td>
<td><input type="file" name="photo" size="10"/></td>
<td><p>Result( jpeg, 450X500): </p>
</td>
<td><input type="file" name="photo1" size="10"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Save">
</td>
</tr>
</table>
<p> </p>
</form>
</center>
 <br /> </td>
<td> </td>
</tr>
<tr>
<td width="4"> <br />
<br /> </td>
<td width="35"> </td>
<td width="505"> </td>
<td width="547"> </td>
</tr>
</table>
</body>
</html>
But after uploading a file, I get this error:
The requested URL /reg/FileUploadDBServlet was not found on this server.
Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request.
Change
action="FileUploadDBServlet"
To
action="<%= request.getContextPath () %>/FileUploadDBServlet"
and try again - the relative path was probably not found under the path.

Forwarding to same page with same managed bean

I am usnig jsf 2.1 and PrimeFaces 4.0.
I have simple html page index.html which is having a link as :
<a href="pages/findus.jsf">
this link open's a page findus.jsf, on this page I have command button as:
<p:commandButton value="Find" action="#{findUsBean.onClickBtnFindUs}">
in onClickBtnFindUs I need setup some values to fields of FindUsBean and redirect to same page means findus.jsf and want to retrieve that values on findus.jsf page.
following is my complete FindUsBean.
#ManagedBean(name = "findUsBean")
#RequestScoped
public class FindUsBean implements Serializable{
private static final long serialVersionUID = 1L;
#ManagedProperty(value = "#{findUsService}")
private FindUsService findUsService;
private String state;
private String city;
private String zip;
private String result;
public String onClickBtnFindUs(){
RestaurantLocationMaster restoLoc = new RestaurantLocationMaster();
System.out.println(getState());
restoLoc.setResState(getState());
restoLoc.setResCity(getCity());
restoLoc.setResZip(getZip());
restoLoc = findRestaurantLocation(restoLoc);
if(null != restoLoc){
setState(restoLoc.getResState());
setCity(restoLoc.getResCity());
setZip(restoLoc.getResZip());
setResult(restoLoc.getResAddress1()+","+restoLoc.getResAddress2());
}else{
setResult("Comming soon...");
}
System.out.println(getState() +""+getCity());
return "/pages/findus.jsf";
}
public RestaurantLocationMaster findRestaurantLocation(RestaurantLocationMaster restoLoc){
RestaurantLocationMaster restoLoc1 = null;
restoLoc1 = findUsService.findRestaurantLocation(restoLoc);
return restoLoc1;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getZip() {
return zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public void setFindUsService(FindUsService findUsService) {
this.findUsService = findUsService;
}
public FindUsService getFindUsService() {
return findUsService;
}
public void setResult(String result) {
this.result = result;
}
public String getResult() {
return result;
}
}
and my findus.jsf is:
<h:form prependId="false" method='POST'>
<table>
<tr>
<td><p:outputLabel value="State"></p:outputLabel>
</td>
<td><p:inputText maxlength="20" value="#{findUsBean.state}"></p:inputText>
</td>
</tr>
<tr>
<td><p:outputLabel value="city"></p:outputLabel>
</td>
<td><p:inputText maxlength="20" value="#{findUsBean.city}"></p:inputText>
</td>
</tr>
<tr>
<td><p:outputLabel value="zip"></p:outputLabel>
</td>
<td><p:inputText maxlength="8" value="#{findUsBean.zip}"></p:inputText>
</td>
</tr>
<tr>
<td colspan="2" align="right"><p:commandButton value="Find"
action="#{findUsBean.onClickBtnFindUs}">
</p:commandButton>
</td>
</tr>
<tr>
<td colspan="2"></td>
</tr>
<tr>
<td></td>
<td><p:inputTextarea value="#{findUsBean.result}"
readonly="true"></p:inputTextarea>
</td>
</tr>
</table>
I am not able to get values. If this is wrong way then please suggest me proper one.
The problem ist the scope of your bean. You should use #ViewScope or a larger scope.
Have a look
here

Manage back and forward in Richfaces

I'm using RichFaces component library and I want to manage the history of Ajax navigation, so the enduser can use the browser back and forward buttons.
Is there any clean way to do it, design pattern, library, etc?
You can use RSH to handle Ajax history
For the example lets assume that you have a page where the user should select a color.
Then, the selected color is posted to the server using XmlHttpRequest.
Now we want to restore previous selection when the back and forward navigation buttons is pressed.
Code Example
Bean:
public class Bean {
private static final String DAFAULT_COLOR = "green";
private Map<String, Color> colors;
private Color selectedColor;
private String restoredColor;
#PostConstruct
public void init() {
this.colors = new HashMap<String, Color>();
this.colors.put("green", new Color("Green", "008000"));
this.colors.put("blue", new Color("Blue", "0000FF"));
this.colors.put("red", new Color("Red", "FF0000"));
this.colors.put("purple", new Color("Purple", "FF0000"));
this.colors.put("purple", new Color("Purple", "800080"));
this.colors.put("yellow", new Color("Yellow", "FFFF00"));
this.colors.put("silver", new Color("Silver", "C0C0C0"));
this.colors.put("black", new Color("Black", "000000"));
this.colors.put("white", new Color("White", "FFFFFF"));
this.selectedColor = this.colors.get(DAFAULT_COLOR);
}
public void setSelectedColor(ActionEvent event) {
UIComponent component = event.getComponent();
String color = ((String)component.getAttributes().get("color")).toLowerCase();
this.selectedColor = this.colors.get(color);
}
public void restoreColor() {
if(restoredColor.equals("") || restoredColor.equals("null")) {
restoredColor = DAFAULT_COLOR;
}
this.selectedColor = this.colors.get(restoredColor);
}
public List<Color> getColors() {
return Arrays.asList(colors.values().toArray(new Color[0]));
}
public Color getSelectedColor() {
return selectedColor;
}
public String getRestoredColor() {
return restoredColor;
}
public void setRestoredColor(String restoredColor) {
this.restoredColor = restoredColor.toLowerCase();
}
}
View:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:c="http://java.sun.com/jstl/core"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich"
template="/WEB-INF/template/default.xhtml">
<ui:define name="head">
<script type="text/javascript" src="#{request.contextPath}/js/rsh/rsh.js"></script>
<script type="text/javascript">
window.dhtmlHistory.create({
toJSON: function(o) {
return Object.toJSON(o);
},
fromJSON: function(s) {
return s.evalJSON();
}
});
Event.observe(window, 'load', function() {
dhtmlHistory.initialize();
dhtmlHistory.addListener(handleHistoryChange);
});
var registerHistoryPoint = function(newLocation, historyData) {
dhtmlHistory.add(newLocation, historyData);
};
</script>
</ui:define>
<ui:define name="content">
<a4j:form id="frmColor">
<div class="colors">
<ul>
<a4j:repeat value="#{bean.colors}" var="color">
<li style="background:##{color.hex};">
<a4j:commandLink value=" "
actionListener="#{bean.setSelectedColor}"
reRender="frmColor"
oncomplete="registerHistoryPoint('#{color.name}', '#{color.name}');">
<f:attribute name="color" value="#{color.name}"/>
</a4j:commandLink>
</li>
</a4j:repeat>
</ul>
</div>
<div class="selection" style="background:##{bean.selectedColor.hex};">
<div class="selected-color"
style="color: ##{bean.selectedColor.name eq 'White' or
bean.selectedColor.name eq 'Yellow' ? '000000' : 'ffffff'}">
<h:outputText value="#{bean.selectedColor.name}"/>
</div>
</div>
<a4j:jsFunction name="handleHistoryChange" reRender="frmColor"
action="#{bean.restoreColor}">
<a4j:actionparam name="historyData" assignTo="#{bean.restoredColor}" />
</a4j:jsFunction>
</a4j:form>
</ui:define>
</ui:composition>
Now when the user click on a color the registerHistoryPoint is invoked. This will register historyData that will be passed to the bean when the back and forward buttons is pressed.
e.g.
User select Yellow.
Yellow is registered.
User select Blue.
Blue is registered.
User click on back.
Yellow is restored.
User click forward.
Blue is restored.

Resources