JSF - Create a Dynamic Menu by using AJAX & selectOneListbox - ajax

What I'd like to do is simple to explain :
bean
#ManagedBean
#ViewScoped
public class Articles {
private String selectedMenu;
#PostConstruct
public void init() {
if(selectedMenu==null || selectedMenu.trim().isEmpty()) {
this.selectedMenu="0";
}
}
public String getSelectedMenu() { return selectedMenu; }
public void setSelectedMenu(String selectedMenu) { this.selectedMenu = selectedMenu; }
}
page
<h:selectOneListbox onchange="..?? ajax call that render on loadMenu and pass the value of the focused listbox to Articles Bean" id="category" size="0" >
<f:selectItem itemLabel="first" itemValue="0" />
<f:selectItem itemLabel="second" itemValue="1" />
<f:selectItem itemLabel="third" itemValue="2" />
</h:selectOneListbox>
<h:panelGroup layout="block" id="loadMenu">
<h:panelGroup rendered="#{articles.selectedMenu=='0'}">
MENU 0
</h:panelGroup>
<h:panelGroup rendered="#{articles.selectedMenu=='1'}">
MENU 1
</h:panelGroup>
<h:panelGroup rendered="#{articles.selectedMenu=='2'}">
MENU 2
</h:panelGroup>
</h:panelGroup>
When I change the value of the listbox, the menu should change dinamically (by calling some function on the server). I think that the code above expresses what I'm looking for.
I must know how call it using the onchange option. Is it possible?
Cheers
UPDATE
<h:panelGroup layout="block">
<h:selectOneListbox styleClass="article_combo" size="0" id="selectedMenu" >
<f:selectItem itemLabel="first" itemValue="0" />
<f:selectItem itemLabel="second" itemValue="1" />
<f:selectItem itemLabel="third" itemValue="2" />
<f:ajax event="change" execute="#this" render="loadMenu" />
</h:selectOneListbox>
</h:panelGroup>
<h:panelGroup layout="block" id="loadMenu">
<h:panelGroup rendered="#{articles.selectedMenu=='0'}">
MENU 0
</h:panelGroup>
<h:panelGroup rendered="#{articles.selectedMenu=='1'}">
MENU 1
</h:panelGroup>
<h:panelGroup rendered="#{articles.selectedMenu=='2'}">
MENU 2
</h:panelGroup>
</h:panelGroup>

You can use the ajax support built in to JSF 2 to achieve this. To do this nest an f:ajax tag in your h:selectOneListbox tag. The f:ajax tag should look like:
<f:ajax render="loadMenu" execute="#this" />
This should process the changed value in your list box, and re-render the panelGroup.
for further details, see:
http://mkblog.exadel.com/2010/04/learning-jsf-2-ajax-in-jsf-using-fajax-tag/

Related

Why p:ajax refresh whole page ? I am using PrimeFace5.0 and JSF 2

To be more specific, I want to use disable calendar component when selectOneMenu component change its value!
<h:form>
<h:panelGrid columns="2" id="Panel" >
<p:calendar id="deadLineDate" value="# {projectsControllerCreate.selected.deadLineDate}" disabled="#{listenerFromSelectOneMenu}" >
</p:calendar>
<p:selectOneMenu id="listUrgent" value="#{projectsControllerCreate.selected.listUrgent}">
<p:ajax update="deadLineDate" event="change" listener="#{bean.listenerFromSelectOneMenu}">
<f:selectItem itemLabel="1" itemValue="1" />
<f:selectItem itemLabel="2" itemValue="2" />
</p:selectOneMenu>
</h:panelGrid>
</h:form>
My listenerFromSelectOneMenu looks like this.
public boolean listenerFromSelectOneMenu() {
Date d = deadLine;
String urg = current.getListUrgent();
String hackUrg = "";
hackUrg = (urg==null) ? "":urg;
return !hackUrg.isEmpty();
}
But whole page is refreshing every time!

selectOneButton change listener always returning null

I'm using JSF 2 along with primefaces, i have a selectOneButton which have 2 values, EN/FR, i want to be notified each time the language is changed, and then change the locale of the page, i have set valueChangeListener and an ajax event,
but everytime the change listener is fired, the new value is always null!
here is the xhtml code:
<h:form id="f">
<p:selectOneButton id="lang" value="#{currentUser.language}" valueChangeListener="#{currentUser.languageChanged}" >
<f:selectItem itemLabel="English" itemValue="en" />
<f:selectItem itemLabel="Françcais" itemValue="fr" />
<f:ajax event="change"/>
</p:selectOneButton>
</h:form>
the languageChanged method for testing:
public void languageChanged(ValueChangeEvent event) {
System.out.println("new val: " + event.getNewValue());
System.out.println("old val: " + event.getOldValue());
}
i even tried to attach to the ajax a listener:
<f:ajax event="change" listener="#{currentUser.languageChanged}"/>
and the method:
public void languageChanged(AjaxBehaviorEvent event) {
SelectOneButton button = (SelectOneButton)event.getComponent();
System.out.println(button.getValue()) ;
}
Is this the wrong way to retrieve the new selected value from a p:selectOneButton with ajax?
UPDATE:
So i know what is causing this problem
actually my selectOneButton is inside a menuItem which is inside a splitButton, when i take the selectOneButton out side the splitButton it works fine!
why is the fact that the selectOneButton is inside the menuItem preventing it from send it to the server?
here the code:
<h:panelGroup style="float: right;" >
<h:form id="f">
<p:splitButton value="#{currentUser.fullName}" icon="ui-icon-person" styleClass="toTheRight" style="min-width: 200px;" >
<p:menuitem value="Matricule: #{currentUser.matricule}" />
<p:menuitem value="#{msgs.role}: #{currentUser.role}" />
<p:separator />
<p:menuitem>
<p:selectOneButton id="lang" value="#{currentUser.language}" valueChangeListener="#{currentUser.languageChanged}" >
<f:selectItem itemLabel="English" itemValue="en" />
<f:selectItem itemLabel="Françcais" itemValue="fr" />
<f:ajax event="change"/>
</p:selectOneButton>
</p:menuitem>
<p:separator />
<p:menuitem value="#{msgs.settings}" icon="ui-icon-wrench" />
<p:menuitem value="#{msgs.logout}" icon="ui-icon-arrowthickstop-1-w" url="/j_spring_security_logout"/>
</p:splitButton>
</h:form>
</h:panelGroup>
I have a similiar snap-code and that should work, here is what i have:
<p:outputLabel for="scriptMigrate" value="Migrate" style="font-weight:bold" />
<p:selectOneButton id="scriptMigrate" value="#{scriptConfiguration.scriptMigrate}" required="true">
<f:selectItem itemLabel="Yes" itemValue="1" />
<f:selectItem itemLabel="No" itemValue="0" />
<p:ajax update="fsstobe" event="change" listener="#{scriptConfiguration.updateForm()}" />
</p:selectOneButton>
The update componetent is just for me to know what to render or not in the rest of the page, but here is the method:
public void updateForm() {
System.out.println("entered with value: " + scriptMigrate);
if (scriptMigrate.equals("1")) {
renderScriptAsIs = true;
}
if (scriptMigrate.equals("0") || scriptMigrate.equals("")) {
renderScriptAsIs = false;
}
}
So i assume when you change the value you just want to call the method languageChanged(), so maybe my example helps, i have no arguments, try without them first to see if it helps.
Could you try
<p:ajax listener="#{currentUser.languageChanged}"/>
and remove the valueChangeListener from the selectOneButton.
In languageChanged(AjaxBehaviorEvent event) just read the new value from the language-property.
<p:selectOneButton value="#{languageBean.languageName}">
<p:ajax listener="#{languageBean.changeLanguage()}" partialSubmit="true"/>
<f:selectItem itemLabel="DE" itemValue="#{CONST.LANGUAGE_DE}"/>
<f:selectItem itemLabel="EN" itemValue="#{CONST.LANGUAGE_EN}" />
</p:selectOneButton>
and in the method from bean:
public void changeLanguage() {
System.out.println(languageName);
}

JSF page does not retrieve values from back bean

I'm doing a dynamic view according to a dropdown selection:
there's the code:
<h:selectOneMenu value="#{controller.type}" >
<p:ajax listener="#{controller.switchPanels}" update="panels" />
<f:selectItem itemValue="1" itemLabel="option 1" />
<f:selectItem itemValue="2" itemLabel="option 2" />
</h:selectOneMenu>
<h:panelGroup layout="block" id="panels">
<h:panelGroup layout="block" rendered="#{controller.type == '1'}" >
<h:inputText value="#{controller.value}" >
<f:validateRegex pattern="^[0-9a-zA-Z ]*$" />
</h:inputText>
</h:panelGroup>
<h:panelGroup layout="block" rendered="#{controller.type == '2'}" >
Panel 2
</h:panelGroup>
</h:panelGroup>
<h:commandLink action="#{controller.go}">Go</h:commandLink>
The controller:
#ViewScoped
#ManagedBean
public class Controller {
String type = "1";
String value;
// getters and setters
public void switchPanels(AjaxBehaviorEvent event) {
this.value = "";
}
public void go(){
}
...
}
Try this scenario:
- write special characters in the value field
- press Go (causes the validation message to popup)
- try changing the selection and reselect the same panel again
The result is that the field is not cleared even though I clear it in the switchPanels method
Please any explanation would be helpful
Thank you

Ajax not rendering new data for <h:selectOneMenu>

I am trying to update a selectOneMenu from the results of another selectOneMenu.
When group is selected the user menu should be updated.
I have verified that the data for the user menu is being updated. It is not being rendered however.
Currently running Primefaces 3.4.2 and JSF 2.1
<ui:composition>
<br/><br/>
<h:form id="transferForm">
<h:panelGrid columns="1" style="width: 500px;margin: auto;text-align: center" >
<h:panelGroup>
<h:outputLabel for="group" value="Group" />
<h:selectOneMenu id="group" value="#{projectBean.transferUtil.selectedTransferGroup}" >
<f:selectItems value="#{projectBean.transferUtil.transferGroups}" />
<f:ajax execute="group" render="user" />
</h:selectOneMenu>
<br />
<h:outputLabel for="user" value="User" />
<h:selectOneMenu id="user" value="#{projectBean.transferUtil.selectedTransferUser}" required="true" requiredMessage="Select User" >
<f:selectItems value="#{projectBean.transferUtil.transferUsers}" />
</h:selectOneMenu>
</h:panelGroup>
<p:commandButton id="projectTransferButton" action="#{projectBean.transferUtil.transfer}" value="Transfer" update=":projtabs,:growlForm:growlMesg">
<f:setPropertyActionListener target="#{projectBean.activeTab}" value="#{projectBean.project_tab_index}" />
</p:commandButton>
</h:panelGrid>
</h:form>
<br/><br/>
[EDIT]
Alright this is the error I am getting.
<?xml version='1.0' encoding='UTF-8'?>
<partial-response><error><error-name>class java.lang.IllegalArgumentException</error-name><error-message><![CDATA[rss02.1 OPERA]]></error-message></error></partial-response>
And this is the code in question.
<p:dataGrid var="area" value="#{projectBean.projectUtil.project.rssAreas}" columns="1">
<p:column>
<h:selectBooleanCheckbox id="rss#{area.shortName}" label="#{area.name}" value="#{area.active}" />
<h:outputText value="#{area.name}" />
</p:column>
</p:dataGrid>
You should not perform business logic in getters/setters. They are invoked multiple times in JSF lifecycle and are intented to get and set the property. You should perform business logic in action(listener) methods instead.
The following construct should work:
<h:selectOneMenu id="group" value="#{projectBean.transferUtil.selectedTransferGroup}" >
<f:selectItems value="#{projectBean.transferUtil.transferGroups}" />
<f:ajax execute="group" listener="#{projectBean.transferGroupChanged}" render="user" />
</h:selectOneMenu>
<h:selectOneMenu id="user" value="#{projectBean.transferUtil.selectedTransferUser}" required="true" requiredMessage="Select User" >
<f:selectItems value="#{projectBean.transferUtil.transferUsers}" />
</h:selectOneMenu>
With
public void transferGroupChanged(AjaxBehaviorEvent event) {
// Change the transferUsers here.
}
The getters and setters should not contain any business logic. They should merely get and set the property.
See also:
Why JSF calls getters multiple times
How to load and display dependent h:selectOneMenu on change of a h:selectOneMenu

How to dynamically change panelGroup using selectOneListBox and AJAX

I want to change the look of the menu based on the selected item.
how to get the value of selectonelistbox using managed bean?
Bean source:
public void selectOneMenuListener(ValueChangeEvent event) {
Object newValue = (String) event.getNewValue();
selectedMenu = newValue.toString();
}
public String getSelectedMenu() {
return selectedMenu;
}
public void setSelectedMenu(String selectedMenu) {
this.selectedMenu = selectedMenu;
}
Page:
<h:panelGroup id="panel">
<h:selectOneListbox id="katProduktu" valueChangeListener="#{produkt_KatBean.selectOneMenuListener}">
<f:selectItems value="#{produkt_KatBean.produkt_KatAllList}"
var="pk" itemLabel="#{pk.symbol}" itemValue="#{pk.id}"/>
<f:ajax render="produktMenu" event="change" execute="#this" />
</h:selectOneListbox>
</h:panelGroup>
<h:panelGroup layout="block" id="produktMenu">
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==1}">
Menu 1
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==2}">
Menu 2
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==3}">
Menu 3
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==4}">
Manu 4
</h:panelGroup>
</h:panelGroup>
Thanks!
Don't use valueChangeListener. It's the wrong tool for the job. Just bind the property to the value attribute of the menu component and let the rendered attribute intercept on that. This way you don't need a listener at all. Also your rendered comparisons won't work for strings. You should have used == '1' instead of == 1 and so on, but this is plain clumsy, just make it Long (or Integer).
<h:panelGroup id="panel">
<h:selectOneListbox id="katProduktu" value="#{produkt_KatBean.selectedMenu}">
<f:selectItems value="#{produkt_KatBean.produkt_KatAllList}"
var="pk" itemLabel="#{pk.symbol}" itemValue="#{pk.id}"/>
<f:ajax render="produktMenu" />
</h:selectOneListbox>
</h:panelGroup>
<h:panelGroup layout="block" id="produktMenu">
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==1}">
Menu 1
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==2}">
Menu 2
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==3}">
Menu 3
</h:panelGroup>
<h:panelGroup rendered="#{produkt_KatBean.selectedMenu==4}">
Manu 4
</h:panelGroup>
</h:panelGroup>
With just
private Long selectedMenu; // Or Integer? Should be the same type as #{pk.id}.
// +getter +setter
(note that I omitted the event and execute attributes of <f:ajax> as they represented the default values already)

Resources