issue while loading data - ajax

I have multiple forms in page and each form have datatables.
When i select the datatable mapped to that control should be shown on the page .
Facing the below exception when developing application using primefaces:
javax.faces.view.facelets.TagAttributeException: //C:/Workspace/Application/WebContent/transfer.xhtml #28,102 rendered="#{transferMB.mySelectedValues('1')}" Error Parsing: #{transferMB.mySelectedValues('1')}
at com.sun.faces.facelets.tag.TagAttributeImpl.getValueExpression(TagAttributeImpl.java:428)
at com.sun.faces.facelets.tag.TagAttributeImpl.getValueExpression(TagAttributeImpl.java:378)
at com.sun.faces.facelets.tag.jsf.ComponentRule$ValueExpressionMetadata.applyMetadata(ComponentRule.java:107)
at com.sun.faces.facelets.tag.MetadataImpl.applyMetadata(MetadataImpl.java:81)
at javax.faces.view.facelets.MetaTagHandler.setAttributes(MetaTagHandler.java:129)
at javax.faces.view.facelets.DelegatingMetaTagHandler.setAttributes(DelegatingMetaTagHandler.java:102)
weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2277)
at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2183)
at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1454)
at weblogic.work.ExecuteThread.execute(ExecuteThread.java:209)
at weblogic.work.ExecuteThread.run(ExecuteThread.java:178)
Caused by: javax.el.ELException: Error Parsing: #{transferMB.mySelectedValues('1')}
at com.sun.el.lang.ExpressionBuilder.createNodeInternal(Unknown Source)
at com.sun.el.lang.ExpressionBuilder.build(Unknown Source)
at com.sun.el.lang.Expres
sionBuilder.createValueExpression(Unknown Source)
at com.sun.el.ExpressionFactoryImpl.createValueExpression(Unknown Source)
at com.sun.faces.facelets.tag.TagAttributeImpl.getValueExpression(TagAttributeImpl.java:412)
... 94 more

You should use comma to separate forms you are going to update like:
<p:ajax update=":transForm, :sprdForm" />
It means there are two forms to be updated.
If you code like:
<p:ajax update=":transForm :sprdForm" />
Means you want to update sprdForm in the transForm, which it not possible since you can't put a form in another form.

You are trying to compare a list with a single String:
rendered="#{transferMB.selectedItems == '1'}"
But instead, you should check if the list INCLUDES this single string:
In the html:
rendered="#{denemeBean.controlSelectedValues('1')}"
In the bean class:
// list should be initialized (unless, we'll get NullPointer
// when using the below method)
private List<String> selectedItems = new ArrayList<>();
// This methods returns true if parameter is included in the
// list of selected items
public boolean controlSelectedValues(String needed) {
for (String string : selectedItems) {
if (string.equals(needed)) {
return true;
}
}
return false;
}
Finally, I'm not sure if you really need to put those datatables inside forms.
Below you can see working copy that I worked on: (of course you should replace outputTexts with your datatables)
// bean file
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
#ManagedBean(name = "denemeBean")
#ViewScoped
public class DenemeBean implements Serializable {
private List<String> selectedItems = new ArrayList<>();
/**
* #return the selectedItems
*/
public List<String> getSelectedItems() {
return selectedItems;
}
/**
* #param selectedItems the selectedItems to set
*/
public void setSelectedItems(List<String> selectedItems) {
this.selectedItems = selectedItems;
}
public boolean controlSelectedValues(String needed) {
for (String string : selectedItems) {
if (string.equals(needed)) {
return true;
}
}
return false;
}
}
// html file:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title></title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</h:head>
<h:body>
<h:form>
<h:selectManyCheckbox value="#{denemeBean.selectedItems}">
<f:selectItem itemValue="1" itemLabel="Transfer Status" />
<f:selectItem itemValue="2" itemLabel="Spread Status" />
<f:selectItem itemValue="3" itemLabel="Number1 - 3" />
<p:ajax event="change" update=":tables" />
</h:selectManyCheckbox>
</h:form>
<p:panel id="tables" >
<p:panel id="transForm" rendered="#{denemeBean.controlSelectedValues('1')}">
<h:outputText value="table1 Here" />
</p:panel>
<p:panel id="sprdForm" rendered="#{denemeBean.controlSelectedValues('2')}">
<h:outputText value="table 2 Here" />
</p:panel>
</p:panel>
</h:body>
</html>

Using <p:ajax update=":transForm :sprdForm" /> is totally valid.
You have multiple other issues here.
First point: Your rendered-attribute compares a List with a String (selectedItems=='1'). It should test if the List contains the String (selectedItems.contains('1')). (Attention: You must use EL 2.2 for this)
Second point is: I think <p:panelGrid> needs the columns-attribute.
I stripped down your code and this works fine for me:
<h:body>
<h:form>
<p:selectManyCheckbox value="#{transferMB.selectedItems}">
<f:selectItem itemValue="1" itemLabel="Transfer Status" />
<f:selectItem itemValue="2" itemLabel="Spread Status" />
<f:selectItem itemValue="3" itemLabel="Number1 - 3" />
<p:ajax update=":transForm :sprdForm"/>
</p:selectManyCheckbox>
</h:form>
<h:form id="transForm">
<p:panelGrid columns="1" rendered="#{transferMB.selectedItems.contains('1')}">
transForm
</p:panelGrid>
</h:form>
<h:form id="sprdForm">
<p:panelGrid columns="1" rendered="#{transferMB.selectedItems.contains('2')}">
sprdForm
</p:panelGrid>
</h:form>
</h:body>
I used <p:selectManyCheckbox> because <h:selectManyCheckbox> with inner <p:ajax> resulted in java.lang.ClassCastException: java.lang.Boolean cannot be cast to org.primefaces.component.api.ClientBehaviorRenderingMode. I think this could be a bug in my JSF Implementation jsf-impl-2.1.7-jbossorg-2.jar.

Related

Conditionally render h:selectOneMenu and h:inputText by ajax depending on h:selectOneRadio selection

I have a form with 2 radio buttons: "type1" and "type2". If "type1" is chosen, then a dropdown must be displayed. If "type2" is chosen, then a textfield must be displayed.
Here's the view and the controller:
test.xtml
<!DOCTYPE composition 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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">
<h:form>
<h:selectOneRadio
id="type"
label="Type"
value="#{testBean.type}">
<f:selectItem itemLabel="Type1" itemValue="type1" />
<f:selectItem itemLabel="Type2" itemValue="type2" />
<f:ajax execute="#all" render="selectBox inputBox"/>
</h:selectOneRadio>
<h:selectOneMenu
id="selectBox"
label="Service"
value="#{testBean.service}"
rendered="#{testBean.isType1}"
style="width:285px">
<f:selectItem itemLabel="Medium" itemValue="medium" />
<f:selectItem itemLabel="Basic" itemValue="basic" />
<f:selectItem itemLabel="Premium" itemValue="premium" />
</h:selectOneMenu>
<h:inputText
id="inputBox"
size="50"
value="#{testBean.custom}"
rendered="#{!testBean.isType1}" />
</h:form>
</ui:composition>
TestBean.java
package com.test.backing;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name = "testBean")
#SessionScoped
public class TestBean implements Serializable
{
private static final long serialVersionUID = -4337084623546767911L;
private String type = "type1";
private String service;
private String custom;
public Boolean getIsType1()
{
if(type.equals("type1"))
{
System.out.println(type+":true");
return true;
}
else
{
System.out.println(type+":false");
return false;
}
}
public String getType()
{
return type;
}
public void setType(String type)
{
this.type = type;
}
public String getService()
{
return service;
}
public void setService(String service)
{
this.service = service;
}
public String getCustom()
{
return custom;
}
public void setCustom(String custom)
{
this.custom = custom;
}
}
When I start my application, I have the following in my stdout:
type1:true
type1:true
type1:true
type1:true
type1:true
type1:true
However, nothing happens in the UI when I choose another type. How is this caused and how can I solve it?
Try to replace xhtml code with the following code
<!DOCTYPE composition 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:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:rich="http://richfaces.org/rich"
xmlns:a4j="http://richfaces.org/a4j">
<h:head>
</h:head>
<h:form prependId="false">
<h:selectOneRadio
id="type"
label="Type"
value="#{testBean.type}">
<f:selectItem itemLabel="Type1" itemValue="type1" />
<f:selectItem itemLabel="Type2" itemValue="type2" />
<f:ajax execute="#all" render="selectInputPanel"/>
</h:selectOneRadio>
<h:panelGroup id="selectInputPanel">
<h:selectOneMenu
id="selectBox"
label="Service"
value="#{testBean.service}"
rendered="#{testBean.isType1}"
style="width:285px">
<f:selectItem itemLabel="Medium" itemValue="medium" />
<f:selectItem itemLabel="Basic" itemValue="basic" />
<f:selectItem itemLabel="Premium" itemValue="premium" />
</h:selectOneMenu>
<h:inputText
id="inputBox"
size="50"
value="#{testBean.custom}"
rendered="#{!testBean.isType1}" />
</h:panelGroup>
</h:form></ui:composition>
Main problem in your code is,
Missing h:head to import jsf.js which is required for jsf ajax.
Please wrap your component into a panelGroup as suggested by #BaluC because once the component not rendered (not available on page) then the ajax on it will not work with its id.
And regarding number of time getIsType1() method calling is due to the rendered attribute, for more information check #Baluc's answer here
JSF generates HTML. JS/Ajax works on HTML. JS/Ajax updates HTML elements by finding it in HTML DOM tree by document.getElementById() and replacing its contents based on Ajax response. However, if a JSF component is instructed to not render HTML, then JS/Ajax cannot find it in the HTML DOM tree and thus can't replace anything.
You can only ajax-update the HTML representation of a JSF component which is always rendered. So, wrap them in e.g. a <h:panelGroup>.
<h:selectOneRadio ...>
<f:ajax ... render="selectAndInputBox" />
</h:selectOneRadio>
<h:panelGroup id="selectAndInputBox">
<h:selectOneMenu ... rendered="..." />
<h:inputText ... rendered="..." />
</h:panelGroup>
See also:
Why do I need to nest a component with rendered="#{some}" in another component when I want to ajax-update it?
Unrelated to the concrete problem, that getIsType1() method is clumsy. Just do the comparison directly in the view so that you can get rid of it.
<h:selectOneMenu ... rendered="#{testBean.type == 'type1'}" />
<h:inputText ... rendered="#{testBean.type != 'type1'}" />
or perhaps, more matching your initial question,
<h:selectOneMenu ... rendered="#{testBean.type == 'type1'}" />
<h:inputText ... rendered="#{testBean.type == 'type2'}" />

How to get changed <p:calendar> value in backing component

I'm not sure how to properly ask that question but I will try like that:
Question is about Primefaces, JSF2 Calendar in composite.. I want to catch an event that is called after that calendar was changed (and catch its new Date value).
my composite xhtml:
<composite:interface componentType="myComponent">
<composite:attribute name="value" required="true"/>
</composite:interface>
<composite:implementation>
<p:calendar
id="tempCalendar"
pattern="dd.MM.yyyy" value="#{cc.attrs.value}"
valueChangeListener="#{cc.valueChanged}"
validator="DateValidator" converter="MyDateConverter" showOn="button" showButtonPanel="true" navigator="true" >
<p:ajax event="dateSelect" update="#this" listener="#{cc.event1}"/>
</p:calendar>
</composite:implementation>
my composite's bean:
public void valueChanged(Object event) {
log("valueChanged");
}
public void event1(AjaxBehaviorEvent ab) {
log("Event1");
if (ab != null && ab.getSource() != null && ab.getSource() instanceof Calendar) {
//....
}
}
page where I'm using composite:
<cc:inputdate value="#{mainBean.aDate}" />
In code above I'm trying to do catch new value in compotents bean, but log looks like that:
valueChanged
Event1
setADate
When I'm in valueChangedListener I still have old value of calendar. New value is set at the end.
So, first of all I want to have new value in my composites bean.. but my main question is:
How to implement an event in my mainBean, that will catch new value of that calendar when changed ?
EDIT: My composite now:
<composite:interface componentType="myComponent">
<composite:attribute name="value" required="true"/>
<composite:attribute
name="myListener"
method-signature="void listener()" />
</composite:interface>
<composite:implementation>
<h:panelGroup id="container">
<p:calendar
value="#{cc.attrs.value}"
valueChangeListener="#{cc.valueChanged}"
<p:ajax event="dateSelect" update="#this,:buttonpanel" listener="#{cc.attrs.myListener}"/>
</p:calendar>
</h:panelGroup>
</composite:implementation>
And that way I call it in my main page (connected with mainBean):
<cc:inputdate
value="#{mainBean.item.myDate}"
myListener="#{mainBean.event1}"/>
I want to catch evet AFTER change in mainBean.java...
You've specified it as value attribute of the composite, so it should be available in any of the backing component's methods by the inherited UIComponent#getAttributes() as follows:
Object value = getAttributes().get("value");
You can access it from the component's local value.
i.e.,
My Test Facelet
<!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 />
<h:body>
<h:form>
<p:calendar pattern="dd.MM.yyyy">
<p:ajax event="dateSelect" process="#this"
listener="#{testBean.event1}" />
</p:calendar>
</h:form>
</h:body>
</f:view>
</html>
My test bean
import org.primefaces.component.calendar.Calendar;
#ManagedBean(name="testBean")
#SessionScoped
public class TestBackingBean
{
public void event1(AjaxBehaviorEvent ab)
{
if (ab != null)
{
Calendar calendar = (Calendar) ab.getSource();
if(calendar != null)
{
System.out.println(String.format("Newly selected value: %s",
calendar.getLocalValue()));
}
}
}
}

Select a component and display - Ajax

I need to output the text that is selected in the selectOneMenu-list. My code is as follows;
<h:selectOneMenu value="#{DataForm.stationed}" id="globalFilter" onchange="carsTable.filter()" style="width:350px;font-size:13px;" >
<f:selectItems value="#{DataForm.listHotel}" var="user" itemValue="#{user[1]}" itemDisabled="false" itemLabel="#{user[1]}" />
<h:outputText value="#{carsTable[1]}" style="width:350px"/>
</h:selectOneMenu>
How do I code this?
EDIT
This Listbox is within a <datatable>
<h:body>
<h:form id="form1" >
<p:dataTable var="car" value="#{DataForm.listHotels}" widgetVar="carsTable" paginator="true" rows="10" onRowSelectComplete="carDialog.show()" emptyMessage="No hospital found with given criteria" selectionMode="single" onRowSelectUpdate="growl" style="width:1400px;font-size:13px;">
<h:selectOneMenu value="#{DataForm.stationed}" id="globalFilter" onchange="carsTable.filter()" style="width:350px;font-size:13px;" >
<f:selectItems value="#{DataForm.listHotel}" var="user" itemValue="#{user[1]}" itemDisabled="false" itemLabel="#{user[1]}" />
<h:outputText value="#{carsTable[1]}" style="width:350px"/>
</h:selectOneMenu>
</p:dataTable>
<f:ajax render= "#form1" >
<h:selectOneMenu value="#{DataForm.stationed}">
<f:selectItems value="#{DataForm.listHotels}" var="item" itemValue="#{DataForm.listHotels}" itemLabel="#{DataForm.listHotels}" />
</h:selectOneMenu>
</f:ajax>
</h:form>
</h:body>
I think you should remove the nested <h:outputText/> first, it doesn't really make sense at that position. Also, from your question and example code, it doesn't really become clear what PrimeFaces has to do with it.
To output the selected value, simply print the expression #{DataForm.stationed}, since this is the binding that will receive the selected value.
The following example demonstrates this via AJAX, but it would work the same way if you used an action and a regular form submit.
Facelet
<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 />
<h:body>
<h:form id="form">
<f:ajax render="form">
<h:selectOneMenu value="#{selectOneMenuBean.value}">
<f:selectItems value="#{selectOneMenuBean.items}" var="item" itemValue="#{item}" itemLabel="#{item}" />
</h:selectOneMenu>
</f:ajax>
Selected value: #{selectOneMenuBean.value}
</h:form>
</h:body>
</html>
Bean
#ViewScoped
#ManagedBean
public class SelectOneMenuBean {
private List<String> items = Arrays.asList("a", "b", "c");
private String value;
public List<String> getItems() {
return items;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
p.s.
In your code example the EL names for your beans start with a capital. This is a little against the typical conventions. Also, you might want to pay some attention to your names and types. The bean returns something called listHotel, but this is assigned to a variable named user, which is then indexed by an integer. I would recommend aligning names (e.g. collection name = users, variable name user) and using properties instead of indexes (e.g. user.name).

JSF dynamic include using Ajax request [duplicate]

This question already has answers here:
How to ajax-refresh dynamic include content by navigation menu? (JSF SPA)
(3 answers)
Closed 7 years ago.
In JSF2, is it possible to change the of value of src of ui:include dynamically using Ajax request (like for example PrimeFaces p:commandButton)?
Thank you.
<h:form>
<h:commandLink value="Display 2" action="#{fTRNav.doNav()}">
<f:setPropertyActionListener target="#{fTRNav.pageName}" value="/disp2.xhtml" />
</h:commandLink>
</h:form>
<ui:include src="#{fTRNav.pageName}"></ui:include>
That's what I have right now. Is it possible to make it Ajax (using p:commandButton)?
The JSTL tags as proposed in the other answer are not necessary and it is not nicely reuseable.
Here's a basic example using pure JSF (assuming that you runs Servlet 3.0 / EL 2.2, otherwise you indeed need to use <f:setPropertyActionListener> like as in your question):
<h:form>
<f:ajax render=":include">
<h:commandLink value="page1" action="#{bean.setPage('page1')}" />
<h:commandLink value="page2" action="#{bean.setPage('page2')}" />
<h:commandLink value="page3" action="#{bean.setPage('page3')}" />
</f:ajax>
</h:form>
<h:panelGroup id="include">
<ui:include src="#{bean.page}.xhtml" />
</h:panelGroup>
with
private String page;
#PostConstruct
public void init() {
this.page = "page1"; // Ensure that default is been set.
}
// Getter + setter.
here is how I render subcontent dynamically using MnagedBean. First I set page in the center (that will be changed by menu triggers) with private String name="/main_pages/mainpage.xhtml", then each time submenu is clicked the HelloBean resets "name" and contents is updated by update=":content" - then new name is retrieved from Bean:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.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">
<h:head>
<f:facet name="first">
<meta content='text/html; charset=UTF-8' http-equiv="Content-Type"/>
</f:facet>
</h:head>
<h:body>
<p:layout fullPage="true">
<p:layoutUnit position="north" size="150" resizable="true" closable="true" collapsible="true">
<h1>Madeline<br>shop</br></h1>
</p:layoutUnit>
<p:layoutUnit position="south" size="100" closable="true" collapsible="true">
Zapraszamy do odwiedzania naszego biura!
</p:layoutUnit>
<p:layoutUnit position="west" size="175" header="Menu" collapsible="true">
<h:form>
<p:menu>
<f:ajax render=":content">
<p:menuitem value="O naszej agencji" action="#{helloBean.setName('/main_pages/onas.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia pojazdów" action="#{helloBean.setName('/main_pages/ubpoj.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia majątkowe" action="#{helloBean.setName('/main_pages/ubmaj.xhtml')}" update=":content" />
<p:menuitem value="Ubezpieczenia na życie" action="#{helloBean.setName('/main_pages/ubnaz.xhtml')}" update=":content" />
<p:menuitem value="Zapytaj" action="#{helloBean.setName('/main_pages/zapytaj.xhtml')}" update=":content" />
<p:menuitem value="Kontakt" action="#{helloBean.setName('/main_pages/kontakt.xhtml')}" update=":content" />
</f:ajax>
</p:menu>
</h:form>
</p:layoutUnit>
<p:layoutUnit position="center">
<br></br><br></br>
<p:panel id="content">
<ui:include src="#{helloBean.name}" />
</p:panel>
</p:layoutUnit>
</p:layout>
</h:body>
</html>
my ManagedBean:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import java.io.Serializable;
/**
*
* #author root
*/
#ManagedBean
#RequestScoped
public class HelloBean implements Serializable {
/**
* Creates a new instance of HelloBean
*/
private static final long serialVersionUID = 1L;
private String name="/main_pages/mainpage.xhtml";
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
You need to use the <c:if test="condition"> tag around the ui:include and then when the ajax button is clicked, the panel that holds the ui:include is refreshed.
Example:
First make sure that the jstl core taglib is included by inserting the following namespace in the document:
<html xmlns:c="http://java.sun.com/jsp/jstl/core>"
Then, you can use the <c:if> tag as follows :
<c:if test="#{!logBean.loggedIn}">
<ui:include src="loginpage.xhtml" />
</c:if>
<c:if test="#{logBean.loggedIn}">
<ui:include src="home.xhtml" />
</c:if>

The f:ajax listener method in h:selectOneMenu is not executed

The page is generated correctly with appropriate values in managed bean, but ajax events in these two h:selectOneMenus don't works. Listener is not called. An error has to be somewhere within tags, but I don't see it.
<f:view>
<h:form>
<h:messages />
<h:panelGrid columns="3">
<h:outputLabel value="Choose your faculty: *" for="faculties" />
<h:selectOneMenu id="faculties" value="#{registrateStudent.selectedFaculty}" >
<f:ajax event="change" listener="#{registrateStudent.genSpecializations}" execute="faculties" render="specializations" />
<f:selectItems value="#{registrateStudent.listFaculty}" var="curFac" itemLabel="#{curFac.name}" itemValue="#{curFac}" />
</h:selectOneMenu>
<h:message id="message_faculties" for="faculties" />
<h:outputLabel value="Choose your specialization: *" for="specializations" />
<h:selectOneMenu id="specializations" value="#{registrateStudent.selectedSpecialization}" >
<f:selectItems value="#{registrateStudent.listSpecialization}" var="curSpec" itemLabel="#{curSpec.name}" itemValue="#{curSpec}"/>
</h:selectOneMenu>
<h:message id="message_specializations" for="specializations" />
Managed Bean:
#ManagedBean(name = "registrateStudent")
#ViewScoped
public class RegistrateStudent {
private Faculty selectedFaculty;
private List<Faculty> listFaculty;
private Specialization selectedSpecialization;
private List<Specialization> listSpecialization;
private boolean showSpecialization = false;
/** Creates a new instance of RegistrateStudent */
public RegistrateStudent() {
users = new Users();
System.out.println("poaposd1");
student = new Student();
}
#PostConstruct
public void init() {
listFaculty = ff.findAll();
if (listFaculty != null) {
selectedFaculty = listFaculty.get(0);
listSpecialization = sf.findByFaculty(selectedFaculty.getIdFaculty());
if (listSpecialization != null) {
selectedSpecialization = listSpecialization.get(0);
}
else {}
} else {}
}
public void genSpecializations(AjaxBehaviorEvent event) {
if (sf.findByFaculty(selectedFaculty.getIdFaculty()) != null) {
this.showSpecialization = true;
} else {
JsfUtil.addSuccessMessage("faculties", "We don't have specializations for such faculty");
}
}
}
UPDATE:
I've found out a few interesting things:
<f:ajax> tag doesn't work at <h:link>, <h:selectOneMenu>, <h:button>, <h:commandButton>. In this cases incorrect values in render attribute is not noticed, but incorrect value of event attribute generate an error.
<h:outputLabel>, <h:inputText> work with <f:ajax> properly
The <f:ajax> requires jsf.js file being included in the HTML <head>. It contains all JS functions for doing the JSF ajax magic.
To achieve this, ensure that you're using <h:head> instead of <head> in the master template. JSF will then automatically include the necessary <script> element there pointing to jsf.js.
<!DOCTYPE html>
<html lang="en"
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">
<h:head>
<title>Look, with h:head</title>
</h:head>
<h:body>
Put your content here.
</h:body>
</html>
Note that in a bit decent webbrowser with a bit decent webdeveloper toolset like Firefox's Web Developer Toolbar and/or Firebug you should immediately have noticed JS errors like jsf is undefined when the ajax request is to be executed. That should at least have given something to think about.
Update: as per your update
I've found out a few interesting things:
<f:ajax> tag doesn't work at <h:link>, <h:selectOneMenu>, <h:button>, <h:commandButton>. In this cases incorrect values in render attribute is not noticed, but incorrect value of event attribute generate an error.
<h:outputLabel>, <h:inputText> work with <f:ajax> properly.
The <h:link> and <h:button> are intented for GET requests only, not POST requests. It should however work just fine on <h:selectOneMenu> and <h:commandButton>. Don't you have more code into the complete picture which you omitted from the question for simplicity? Which JSF impl/version are you using? Are you using the right libraries in classpath? It look like that you must really have messed up something.
To convince you (and myself) I just created the following copy'n'paste'n'runnable testcase
<!DOCTYPE html>
<html lang="en"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
<h:head>
<title>SO question 6089924</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{bean.selected}">
<f:selectItem itemValue="#{null}" itemLabel="Select..." />
<f:selectItem itemValue="one" />
<f:selectItem itemValue="two" />
<f:selectItem itemValue="three" />
<f:ajax listener="#{bean.listener}" render="result" />
</h:selectOneMenu>
<h:commandButton value="commandButton" action="#{bean.submit}">
<f:ajax listener="#{bean.listener}" render="result" />
</h:commandButton>
<h:outputText id="result" value="#{bean.selected} #{bean.result}" />
<h:messages />
</h:form>
</h:body>
</html>
with this bean
package com.example;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.AjaxBehaviorEvent;
#ManagedBean
#ViewScoped
public class Bean implements Serializable {
private String selected;
private String result;
public void submit() {
System.out.println("submit");
}
public void listener(AjaxBehaviorEvent event) {
System.out.println("listener");
result = "called by " + event.getComponent().getClass().getName();
}
public String getSelected() {
return selected;
}
public void setSelected(String selected) {
this.selected = selected;
}
public String getResult() {
return result;
}
}
It runs fine with Mojarra 2.1.1 on Tomcat 7.0.12.
INFO: Starting Servlet Engine: Apache Tomcat/7.0.12
INFO: Initializing Mojarra 2.1.1 (FCS 20110408) for context '/playground'
Be careful if you have f:metadata and f:viewparam tags since the setters of the parameters will be called with every ajax request.
Can you provide the error log if there is any error/exception that is being generated when you call the ajax call?

Resources