I'm struggling with letting JSF execute the action behind a commandLink. It doesn't seem to execute its action even though it's not in a form that's nested in another form, there shouldn't be any validation errors and the element seems to be rendered properly.
The page is shows details for a flight booking. The button I'm talking about should take a user to a payment page.
The trouble happens all the way in the back of the form in this file (the messages above don't print anything):
<ui:composition template="/WEB-INF/template.xhtml">
<ui:define name="metaData">
<f:metadata>
<f:viewParam name="departureId" value="#{bookingCreationWizard.departureId}"/>
<f:viewParam name="returnId" value="#{bookingCreationWizard.returnId}"/>
</f:metadata>
</ui:define>
<ui:define name="pageTitle">#{msg.flights_details_page_title}</ui:define>
<ui:define name="pageContent">
<h1>#{msg.flights_details_page_title}</h1>
<h:panelGroup layout="block">
<h2>#{msg.flight_details_h2_departure}</h2>
<table>
<tr>
<th>Airline</th>
<th>Class</th>
<th>Seats Remaining</th>
<th>Departure Time</th>
<th>Flight Duration</th>
<th>Arrival Time</th>
<th>Departure Airport</th>
<th>Arrival Airport</th>
<th>Price</th>
</tr>
<tr>
<td>#{bookingCreationWizard.departureFlight.flight.airline.name}</td>
<td>#{bookingCreationWizard.departureFlight.name}</td>
<td>#{bookingCreationWizard.departureFlight.freeSeats}</td>
<td>#{bookingCreationWizard.departureFlight.flight.departureTime}</td>
<td>TODO</td>
<td>#{bookingCreationWizard.departureFlight.flight.arrivalTime}</td>
<td>#{bookingCreationWizard.departureFlight.flight.departureAirport.code}</td>
<td>#{bookingCreationWizard.departureFlight.flight.arrivalAirport.code}</td>
<td>#{bookingCreationWizard.departureFlight.price}</td>
</tr>
</table>
</h:panelGroup>
<h:panelGroup layout="block" rendered="#{bookingCreationWizard.hasReturnFlight()}">
<h2>#{msg.flight_details_h2_return_flight}</h2>
<table>
<tr>
<th>Airline</th>
<th>Class</th>
<th>Seats Remaining</th>
<th>Departure Time</th>
<th>Flight Duration</th>
<th>Arrival Time</th>
<th>Departure Airport</th>
<th>Arrival Airport</th>
<th>Price</th>
</tr>
<tr>
<td>#{bookingCreationWizard.returnFlight.flight.airline.name}</td>
<td>#{bookingCreationWizard.returnFlight.name}</td>
<td>#{bookingCreationWizard.returnFlight.freeSeats}</td>
<td>#{bookingCreationWizard.returnFlight.flight.departureTime}</td>
<td>TODO</td>
<td>#{bookingCreationWizard.returnFlight.flight.arrivalTime}</td>
<td>#{bookingCreationWizard.returnFlight.flight.departureAirport.code}</td>
<td>#{bookingCreationWizard.returnFlight.flight.arrivalAirport.code}</td>
<td>#{bookingCreationWizard.returnFlight.price}</td>
</tr>
</table>
</h:panelGroup>
<h:panelGroup layout="block">
<h2>#{msg.flight_details_h2_price}</h2>
<table>
<tr>
<th>#{msg.flight_details_price_table_flight}</th>
<th>#{msg.flight_details_price_table_amount}</th>
<th>#{msg.flight_details_price_table_total_price}</th>
</tr>
<tr>
<td>#{bookingCreationWizard.departureFlight.flight.departureAirport.code} - #{bookingCreationWizard.departureFlight.flight.arrivalAirport.code}</td>
<td>#{bookingCreationWizard.numberOfPeople}</td>
<td>#{bookingCreationWizard.departureFlight.finalPrice}</td>
</tr>
<h:panelGroup rendered="#{bookingCreationWizard.hasReturnFlight()}">
<td>#{bookingCreationWizard.returnFlight.flight.departureAirport.code} - #{bookingCreationWizard.returnFlight.flight.arrivalAirport.code}</td>
<td>#{bookingCreationWizard.numberOfPeople}</td>
<td>#{bookingCreationWizard.returnFlight.finalPrice}</td>
</h:panelGroup>
</table>
</h:panelGroup>
<h:panelGroup layout="block">
<h:form>
<h:messages style="color:red;margin:8px;"/>
<h:commandLink action="#{bookingCreationWizard.proceedToPayment()}" value="#{msg.flight_details_booking_button}" />
</h:form>
</h:panelGroup>
</ui:define>
</ui:composition>
</html>
Below I've also included the template this file is embedded in, and the #Conversationscoped bean that contains the action that should be executed.
Template:
<?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://java.sun.com/jsf/core" xml:lang="en" lang="en"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<f:view locale="#{languageSwitcherController.locale}">
<h:head>
<title><ui:insert name="pageTitle">#{msg.template_title_addon}</ui:insert></title>
<h:outputStylesheet library="css" name="normalize.css"/>
<h:outputStylesheet library="css" name="skeleton.css"/>
<h:outputStylesheet library="css" name="main.css"/>
<ui:insert name="metaData"/>
<meta name="viewport" content="width=device-width, inital-scale=1.0"/>
</h:head>
<h:body>
<h:form id="langauge_form">
<h:commandLink action="#{languageSwitcherController.changeLanguage('nl_BE')}" value="Nederlands"/> |
<h:commandLink action="#{languageSwitcherController.changeLanguage('en')}" value="English"/>
</h:form>
<!--<h:graphicImage name="01.jpg" library="images" width="500" height="100"/>-->
<h1>#{msg.template_header}</h1>
<div>
<ui:insert name="pageContent">
</ui:insert>
</div>
<br/>
#{msg.template_footer}
</h:body>
</f:view>
</html>
Bean:
#ConversationScoped
#Named
public class BookingCreationWizard implements Serializable {
#Inject
private Conversation conversation;
#Inject
private CategoryService service;
private Long departureId;
private Long returnId;
private Category departureFlight;
private Category returnFlight;
private int numberOfPeople;
#PostConstruct
public void init() {
this.numberOfPeople = 1;
}
public int getNumberOfPeople() {
return this.numberOfPeople;
}
public void setNumberOfPeople(int numberOfPeople) {
if (conversation.isTransient()){
conversation.begin();
}
this.numberOfPeople = numberOfPeople;
}
public Long getDepartureId() {
return departureId;
}
public void setDepartureId(Long departureId) {
this.departureId = departureId;
}
public Long getReturnId() {
return returnId;
}
public void setReturnId(Long returnId) {
this.returnId = returnId;
}
public Category getDepartureFlight() {
if (departureFlight == null) {
this.departureFlight = service.getFlightById(this.departureId);
}
return this.departureFlight;
}
public Category getReturnFlight() {
if (returnFlight == null) {
this.returnFlight = service.getFlightById(this.returnId);
}
return this.returnFlight;
}
public boolean hasReturnFlight() {
return this.returnId != null;
}
public String chooseFlight() {
return "details.jsf?faces-redirect=true";
}
public String proceedToPayment() {
System.out.print("Proceeding");
return "../pay.jsf";
}
}
Related
I am trying to implement simple page navigation. So whenever I click on login button it should simply redirect me to welcome page and show welcome message.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>External Resources</title>
</h:head>
<h:body>
<ui:composition template="/WEB-INF/templates/template.xhtml">
<ui:define name="css">
<h:outputStylesheet library="css" name="index.css"/>
</ui:define>
<ui:define name="content">
<h1>Welcome to Login Page</h1>
<h:form id="login-form" prependId="false">
<h:panelGrid columns="5">
<h:outputLabel for="username" value="Username"/>
<h:inputText id="username" value="#{loginBean.user.username}" />
<h:outputLabel for="password" value="Password"/>
<h:inputSecret id="password" value="#{loginBean.user.password}" />
<h:commandButton value="Login" id="cmdButton"
action="#{loginBean.goToWelcome()}"/>
</h:panelGrid>
</h:form>
</ui:define>
</ui:composition>
</h:body>
</html>
this is my login bean which contains a goToWelcome method which returns string.
LoginBean.java
#SessionScoped
#ManagedBean
public class LoginBean implements Serializable{
private User user;
public LoginBean(){
}
#PostConstruct
public void init(){
user= new User();
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
public String goToWelcome(){
return "/pages/welcome?faces-redirect=true";
}
}
the error says:-
Unable to find matching navigation case with from-view-id
'/index.xhtml' for action '#{loginBean.goToWelcome()}' with outcome
'/pages/welcome?faces-redirect=true'
There are many ways to return a page!
The very simple one : return a page like this for example in your backingBean:
return "DesiredPage.xhtml";
That page must be in WebPages folder.
Hello I have an inputText on blur event that will send a signal to the backing bean, this bean contains a Boolean variable that determines if another input text will be enabled or not ... but I can not make this work, this is my code:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui"
template="/Template.xhtml">
<ui:define name="content">
<h:form id="someForm">
<p:growl id="msg" showDetail="true" life="3000"/>
<p:panelGrid border="0" id="panel">
<p:row>
<p:column width="350">
Title
</p:column>
<p:column colspan="2">
<p:inputText id="someId" value="#{someBean.somePropertie}">
<p:ajax event="blur" update="anotherInput" listener="#{someBean.onEvent}" />
</p:inputText>
</p:column>
</p:row>
<p:row>
<p:column width="350">title 2</p:column>
<p:column colspan="2">
<p:inputText id="anotherInput" converter="toUpperCaseConverter" value="#{someBean.somePropertie2}"
disabled="#{someBean.bDisabled}"
/>
</p:column>
</p:row>
</p:panelGrid>
</h:form>
</ui:define>
</ui:composition>
Backing bean:
#ManagedBean
#SuppressWarnings("serial")
public class SomeBean implements Serializable{
private boolean bDisabled;
private String somePropertie;
private String somePropertie2;
public void onEvent(){
System.out.println("DO SOMETHING");
this.bDisabled = true;
}
... getters and setters of properties and boolean ....
}
this is the main tamplate:
<!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>..:: XXXXX ::..</title>
<meta http-equiv="Pragma" content="no-cache" />
<link rel="stylesheet" type="text/css" href="#{request.contextPath}/css/default.css"/>
<style type="text/css">
.ui-growl{
position:absolute;
top:20%;
left:50%;
z-index:9999;
}
.ui-widget,.ui-widget .ui-widget {
font-family: Trebuchet MS;
}
</style>
</h:head>
<h:body style="background-color: #E1E1E1;">
<div id="page">
<div id="divHeader" style="height: 70px;">
<ui:insert name="header" >
<ui:include src="header.xhtml" />
</ui:insert>
</div>
<div id="divMenu" style="height: 50px;">
<ui:insert name="menu">
<ui:include src="menu.xhtml" />
</ui:insert>
</div>
<div id="divContent">
<ui:insert id="content" name="content" >
<ui:include src="content.xhtml" />
</ui:insert>
</div>
</div>
</h:body>
</html>
the converter:
#FacesConverter("toUpperCaseConverter")
public class ToUpperCaseConverter implements Converter {
#Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
return (String) value;
}
#Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
return (value != null) ? value.toUpperCase() : null;
}
}
any idea ???
Please help :(
Your question is not complete, since it does not provide all the elements to reproduce the bug. You haven't provided the page that calls your element, neither the converter, etc.
JSF's debugger best friend is firebug. Always check for javascript errors and enable the network tab to see each request response body, which may contain "silent" error messages.
I'll take my risk trying to guess your problem :-)
Here's your code, slightly changed to run in my primefaces 4.
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:p="http://primefaces.org/ui">
<h:head>
<title>You NEED a header</title>
</h:head>
<h:body>
<h:form>
<ui:include src="index2.xhtml" />
</h:form>
</h:body>
</html>
and
<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">
<p:growl
id="msg"
showDetail="true"
life="3000" />
<p:panelGrid
border="0"
id="panel">
<p:row>
<p:column width="350">
Title
</p:column>
<p:column colspan="2">
<p:inputText
id="someId"
value="#{someBean.somePropertie}">
<p:ajax
event="blur"
update="anotherInput"
listener="#{someBean.onEvent}" />
</p:inputText>
</p:column>
</p:row>
<p:row>
<p:column width="350">title 2</p:column>
<p:column colspan="2">
<p:inputText
id="anotherInput"
value="#{someBean.somePropertie2}"
disabled="#{someBean.bDisabled}" />
</p:column>
</p:row>
</p:panelGrid>
</ui:composition>
The managed bean is pretty much the same
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
#ManagedBean
#SuppressWarnings("serial")
public class SomeBean implements Serializable {
private boolean bDisabled;
private String somePropertie;
private String somePropertie2;
public void onEvent() {
System.out.println("DO SOMETHING");
this.bDisabled = true;
}
public boolean isbDisabled() {
return this.bDisabled;
}
public void setbDisabled(boolean bDisabled) {
this.bDisabled = bDisabled;
}
public String getSomePropertie() {
return this.somePropertie;
}
public void setSomePropertie(String somePropertie) {
this.somePropertie = somePropertie;
}
public String getSomePropertie2() {
return this.somePropertie2;
}
public void setSomePropertie2(String somePropertie2) {
this.somePropertie2 = somePropertie2;
}
}
I've noticed that if you don't omit the HEAD section from the caller page, it seems to render and work.
But if you forget the HEAD section (you must not, see Primefaces FAQ item #2), you'll render the page (quite) but you'll get some javascript errors and your page won't work. The HEAD section I am talking about is this
<h:head>
<title>You NEED a header</title>
</h:head>
This is how it looks without the HEAD section.
With the HEAD section, it seems to work. Also notice the subtle primefaces look and feel.
What should be the return type for getResponse and submit, and are both necessary?
When a guess is entered in either the firstForm or SecondForm, how do I echo that guess to the same webpage?
Either with ajax, and so not reloading the same page
or
loading a new page, guessResults.xhtml, for example, which echo's the guess.
backing bean, NextClient:
package dur.beans;
import dur.jpa.Client;
import dur.jpa.ClientFacadeLocal;
import java.util.concurrent.atomic.AtomicInteger;
import javax.ejb.EJB;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
#Named("nextClient")
#ApplicationScoped
public class NextClient implements NextClientLocal {
#EJB
private ClientFacadeLocal clientFacade;
private AtomicInteger next = new AtomicInteger(1009);
private AtomicInteger guess = new AtomicInteger(0);
private final boolean correct = true;
#Override
public String getNext() {
next.addAndGet(1);
Client client = clientFacade.find(next.intValue());
return client.toString();
}
#Override
public void setGuess(int guessInt) {
guess = new AtomicInteger(guessInt);
}
#Override
public int getGuess() {
return guess.intValue();
}
//not sure what do with these methods
#Override
public String getResponse() {
return "the guess of " + guess.intValue() + " is " + correct;
}
#Override
public String submit() {
return "the guess of " + guess.intValue() + " is " + correct;
}
}
facelets template client, next.xhtml:
<!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"
>
<h:head></h:head>
<h:body>
This and everything before will be ignored
<ui:composition template="template.xhtml">
<ui:define name="navigation">
<ui:include src="menu.xhtml"/>
</ui:define>
<ui:define name="main">
<h1>next bird</h1>
<p>
#{nextClient.next}
</p>
<p>
<h:panelGroup id="firstPanel">
<h:form id="firstForm">
<h:outputLabel for="input" value="First form input" />
<h:inputText id="input" value="#{nextClient.guess}" required="true" />
<h:commandButton value="Submit form" action="#{nextClient.submit}">
<f:ajax execute="#form" render="#form :secondPanel :secondForm :messages" />
</h:commandButton>
<h:message for="input" />
</h:form>
</h:panelGroup>
<h:panelGroup id="secondPanel">
<h:form id="secondForm">
<h:outputLabel for="input" value="Second form input" />
<h:inputText id="input" value="#{nextClient.guess}" required="true" />
<h:commandButton value="Submit other form" action="#{nextClient.submit}">
<f:ajax execute="#form" render="#form :firstPanel :firstForm :messages" />
</h:commandButton>
<h:message for="input" />
</h:form>
</h:panelGroup>
<h:messages id="messages" globalOnly="true" layout="table" />
</p>
</ui:define>
</ui:composition>
This and everything after will be ignored
</h:body>
</html>
see also:
http://balusc.blogspot.ca/2011/09/communication-in-jsf-20.html#AjaxRenderingOfContentWhichContainsAnotherForm
JSF 2.0 commandButton do nothing
https://javaserverfaces.java.net/nonav/docs/2.0/pdldocs/facelets/h/commandButton.html
http://docs.oracle.com/javaee/7/tutorial/doc/jsf-facelets003.htm
I'm running facelets on Glassfish, using CDI, so am using #Named and not #ManagedBean -- some of the documentation above is more geared for #ManagedBean, but I'm not sure how much that matters.
The goal is one step better than "hello world", "hello world, your guess is " would be a good result. If there's a specific manual, I don't mind a RTFM to that specific documentation. The Oracle docs are probably the best for facelets?
code:
https://github.com/THUFIR/EntAppWeb
This response.xhtml:
<!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">
<h:head>response</h:head>
<h:body>
This and everything before will be ignored
<ui:composition template="template.xhtml">
<ui:define name="navigation">
<ui:include src="menu.xhtml"/>
</ui:define>
<ui:define name="main">
<h1>submitted value</h1>
<p>
#{nextClient.guess}
</p>
<h2>for this bird</h2>
<p>
#{nextClient.client}
</p>
</ui:define>
</ui:composition>
This and everything after will be ignored
</h:body>
</html>
to next.xhtml:
<!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">
<h:head>next</h:head>
<h:body>
This and everything before will be ignored
<ui:composition template="template.xhtml">
<ui:define name="navigation">
<ui:include src="menu.xhtml"/>
</ui:define>
<ui:define name="main">
<h1>next bird</h1>
<p>
#{nextClient.next}
</p>
<p>
<h:panelGroup id="simpleGroup">
<h:form id="simpleForm">
<h:outputLabel for="input" value="First form input" />
<h:inputText id="input" value="#{nextClient.guess}" required="true" />
<h:commandButton value="submit" action="response">
</h:commandButton>
</h:form>
</h:panelGroup>
</p>
</ui:define>
</ui:composition>
This and everything after will be ignored
</h:body>
</html>
using the backing bean NextClient:
package dur.beans;
import dur.jpa.Client;
import dur.jpa.ClientFacadeLocal;
import java.util.concurrent.atomic.AtomicInteger;
import javax.ejb.EJB;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Named;
#Named("nextClient")
#ApplicationScoped
public class NextClient implements NextClientLocal {
#EJB
private ClientFacadeLocal clientFacade;
private AtomicInteger next = new AtomicInteger(1009);
private AtomicInteger guess = new AtomicInteger(0);
private final boolean correct = true;
private Client client = new Client();
#Override
public String getNext() {
next.addAndGet(1);
client = clientFacade.find(next.intValue());
return client.toString();
}
#Override
public void setGuess(int guessInt) {
guess = new AtomicInteger(guessInt);
}
#Override
public int getGuess() {
return guess.intValue();
}
#Override
public Client getClient() {
return client;
}
#Override
public void setClient(Client client) {
this.client = client;
}
}
outputs the submitted value to the response, along with the bird. It might make more sense to output the result to the same page, but this is sufficient.
I'm try to build application with Primefaces 4.0 and JSF 2.2.5. I need to load content dynamically in accordance with choosen menu item.
Here is my main 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">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title>Hello, world!</title>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="west" size="15%">
<h:form>
<p:commandButton value="List1" action="#{backingBean.setCurrentPage('included.xhtml')}"
update=":mypanel_id" process="#this"/><br/>
<p:commandButton value="List2"/>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<p:panel id="mypanel_id">
<ui:include src="#{backingBean.page}"/>
</p:panel>
<p:messages autoUpdate="true" showDetail="true" showSummary="true"/>
</p:layoutUnit>
</p:layout>
</h:body>
</html>
And this is 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">
<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:p="http://primefaces.org/ui">
<h:head>
<title>Hello,world</title>
</h:head>
<h:body>
<h:outputText value="Included page"/>
<h:form>
<ui:repeat value="#{backingBean.items}" var="item">
<p:fieldset legend="item" toggleable="true">
<h:outputText value="#{item}"/>
<ui:param name="it" value="#{item}"/>
<p:commandButton value="Click" style="margin-left: 50px;"
actionListener="#{backingBean.actionListener}"/>
</p:fieldset>
</ui:repeat>
<p:commandButton value="Test" action="#{backingBean.actionListener}"/>
</h:form>
</h:body>
</html>
Command buttons not work. Not with action nor with actionListener. What i'm doing wrong? How to build page with conditionally rendered elements, such as command buttons and fieldsets?
P.S. Forget to say, that my bean have request scope.
Updated:
public class BackingBean {
private List<String> items;
private String currentItem;
private String page;
public BackingBean() {
items = new ArrayList<String>();
}
public List<String> getItems() {
if (items.size() == 0) {
this.fillAndUpdate();
}
return items;
}
public void setItems(List<String> items) {
this.items = items;
}
public void fillAndUpdate() {
for (int i = 0; i < 5; i++) {
items.add("Item " + String.valueOf(i));
}
}
public String getPage() {
return page;
}
public void setPage(String page) {
this.page = page;
}
public void setCurrentPage(String page) {
this.page = page;
}
public void actionListener() {
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Test"));
}
}
UPDATED
Ok. I found the error (if someone interested). Because my bean has request scope, when i click the button in right panel my view was updated, but list of items was updated too and became empty (request scope). Now i keep selected menu in the session bean, and return that number when view rendered.
try to add ajax="false" in your command buttons
I'm usign Mojarra 2.1.23 and Primefaces 3.5. I'm trying to make this code work, but for some reason I can't get the listener to be invoked.
<h:form id="menu" >
<p:growl id="messages" autoUpdate="true" showDetail="true" />
<p:panelMenu>
<p:submenu label="Ajax Menuitems">
<p:menuitem value="#{MenuController.test}"
actionListener="#{MenuController.save}" ajax="true"
update="messages" />
<p:menuitem value="Update" actionListener="#{MenuController.save}"
update="messages" />
</p:submenu>
</p:panelMenu>
</h:form>
MenuController is a session scoped bean managed by Spring 3 and even its properties are properly displayed on the same xhtml (button shows the text "Save").
The MenuController class is as follows:
public class MenuController() implements Serializable{
public static Logger log;
public String test="Save";
public MenuController() {
log = LoggerFactory.getLogger(this.getClass());
log.debug("Hello MenuController.");
}
public void save(ActionEvent event) {
addMessage("Data saved");
log.debug(" saving");
}
public void addMessage(String summary) {
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_INFO,
summary, null);
FacesContext.getCurrentInstance().addMessage(null, message);
}
//getters and setters...
}
I'm also using facelets, the following is Layout.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:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui">
<h:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title><ui:insert name="title" /></title>
</h:head>
<h:body>
<div id="layout">
<table>
<tr>
<td>
<div id="menu">
<ui:include src="menu.xhtml"/>
</div>
</td>
<td>
<div id="content">
<ui:insert name="content">
</ui:insert>
</div>
</td>
</tr>
<tr>
<td>
<div id="footer">
<p>© Footer</p>
</div>
</td>
</tr>
</table>
</div>
When I click the menu entry, the method is not being called.
The problem was solved by changing the id on the form from "menu" to "menuForm", to not be confused by the one on the layout with id "menu"
<h:form id="menuForm" >
<p:growl id="messages" autoUpdate="true" showDetail="true" />
<p:panelMenu>
<p:submenu label="Ajax Menuitems">
<p:menuitem value="#{MenuController.test}"
actionListener="#{MenuController.save}" ajax="true"
update="messages" />
<p:menuitem value="Update" actionListener="#{MenuController.save}"
update="messages" />
</p:submenu>
</p:panelMenu>
</h:form>