Invoke action method on click of h:selectOneMenu - jsf

I have the following drop down list:
<h:selectOneMenu value="#{user.favCoffee3}" onclick="">
<f:selectItems value="#{user.favCoffee3Value}" var="c"
itemLabel="#{c.coffeeLabel}" itemValue="#{c.coffeeValue}" />
</h:selectOneMenu>
I would like to launch some method from the bean by drop down list item click. How can I achieve it?

You can use the valueChangeListener attribute, pointing to a method in the managed-bean and add a submit() in the onchange attribute.
The form should look like :
<h:form>
<h:selectOneMenu valueChangeListener="#{bean.valueChanged}"
onchange="submit()">
<f:selectItem itemValue="1" itemLabel="First" />
<f:selectItem itemValue="2" itemLabel="Second" />
</h:selectOneMenu>
</h:form>
And the valueChangeListener method in the managed bean would be:
public void valueChanged(ValueChangeEvent event) {
//do your stuff
}

As part of the basic JSF toolkit, you can use the <f:ajax/> tag to submit (using ajax) your input without need for a full page submit/refresh. Using your code sample
Define the <f:ajax/> tag as a child of the dropdown menu
<h:selectOneMenu value="#{user.favCoffee3}" onclick="">
<f:selectItems value="#{user.favCoffee3Value}" var="c" itemLabel="#{c.coffeeLabel}" itemValue="#{c.coffeeValue}" />
<f:ajax listener="#{user.doSomething}"/>
</h:selectOneMenu>
Define a method (doSomething() in this example) in your backing bean that accepts an instance of AjaxBehaviorEvent
public void doSomething(AjaxBehaviorEvent abe){
//do what you want with your favCoffee3 variable here
}
Further reading:
The <f:ajax/> tag documentation by oracle

Seems to work for a4j:support. Your h:selectOneMenu would look like this:
<h:selectOneMenu value="#{user.favCoffee3}">
<f:selectItems value="#{user.favCoffee3Value}" var="c" itemLabel="#{c.coffeeLabel}" itemValue="#{c.coffeeValue}" />
<a4j:support event="onchange" action="#{user.onSelectOneMenuChange}">
</h:selectOneMenu>
You also need to add the following taglib:
<%# taglib uri="http://richfaces.org/a4j" prefix="a4j"%>

Related

Reset selectoneMenu with another selectOneMenu without ajax

I want to reset a selectOneMenu with another selectOneMenu to the default value and I can't use ajax.
First menu:
<h:selectOneMenu value="#{bean.rel}" id="relSelection"
valueChangeListener="#{bean.onRelChange}" onchange="submit();"
immediate="true">
<f:selectItems value="#{bean.rel}" />
</h:selectOneMenu>
Menu I want to reset:
<h:selectOneMenu value="#{bean.domSelected}" id="domSelection"
valueChangeListener="#{bean.onDomChange}" onchange="submit()"
hideNoSelectionOption="true" immediate="true" >
<f:selectItem itemValue="#{null}" itemLabel="Select..."
noSelectionOption="true" />
<f:selectItems value="#{bean.domNames}" var="item"
itemLabel="#{item}" itemValue="#{item}"/>
</h:selectOneMenu>
If the first menu is selected after the second already was selected by the user I want to reset the second menu.
I expected that the second menu would display the noSelectionOption after I set its value to null from the onReleaseChange listener, but it keeps the selected value.
Listener:
public void onRelChange(ValueChangeEvent event) {
domSelected = null; //type String
rel = (String) event.getNewValue();
//som other stuff
}
I already tried the remoteCommand approach described here
by adding this:
<p:remoteCommand name="resetInputs" process="#this relSelection"
actionListener="#{bean.clearMenu}" immediate="true">
<p:resetInput target="domSelection" />
</p:remoteCommand>
In the first menu I called the remoteCommand via onChange="submit(); resetInputs()"
Any other Ideas or Ideas why this is not working?
Thanks!
Primefaces 6.1
JSF 2.2
GlassFish 4.1.1

Primefaces p:tabView: Value of selectOneMenu lost

I have a problem when I use a p:tabView with dynamic="true", and there is a h:selectOneMenu on one tab, and on the other is a commandLink which is ajax="false". After clicking to the commandLink twice the value of the selectOneMenu is lost.
This problem does not occur when the tabView is dynamic="false".
The value of the h:inputText is not lost, but I see the following warning in the logfile:
org.apache.myfaces.shared.renderkit.html.HtmlRendererUtils decodeUIInput WARNING: There should always be a submitted value for an input if it is rendered, its form issubmitted, and it was not originally rendered disabled or read-only. You cannot submit a form after disabling an input element via javascript. Consider setting read-only to true instead or resetting the disabled value back to false prior to form submission. Component : {Component-Path : [Class: javax.faces.component.UIViewRoot,ViewId: /form/regional/region.xhtml][Class: javax.faces.component.html.HtmlBody,Id: j_id_5][Class: javax.faces.component.html.HtmlForm,Id: TestForm][Class: org.primefaces.component.tabview.TabView,Id: tabviewTest][Class: org.primefaces.component.tabview.Tab,Id: j_id_8][Class: javax.faces.component.html.HtmlInputText,Id: j_id_f]}
Here is the form:
<p:tabView dynamic="true" cache="true" id="tabviewTest">
<p:tab title="Tab 1">
<h:selectOneMenu value="#{Region.dropDownValue}" id="dropDown">
<f:selectItem itemLabel="" itemValue=""/>
<f:selectItem itemLabel="1" itemValue="1"/>
<f:selectItem itemLabel="2" itemValue="2"/>
<f:selectItem itemLabel="3" itemValue="3"/>
<f:selectItem itemLabel="4" itemValue="4"/>
</h:selectOneMenu>
<h:inputText value="#{Region.inputValue}" />
</p:tab>
<p:tab title="Tab 2">
<p:commandLink ajax="false"
id="link"
value="Test"
actionListener="#{Region.someActionMethod}" />
</p:tab>
</p:tabView>
And here the Bean:
public class Region {
private Integer dropDownValue = 3;
private String inputValue = "Test";
public void someActionMethod(ActionEvent ev) {
System.out.println("someActionMethod called");
}
public Integer getDropDownValue() {
return dropDownValue;
}
public void setDropDownValue(Integer dropDownValue) {
this.dropDownValue = dropDownValue;
}
public String getInputValue() {
return inputValue;
}
public void setInputValue(String inputValue) {
this.inputValue = inputValue;
}
}
My Environment: Primefaces 5.0/5.1.RC1, Myfaces 2.1/2.2, Tomact 7
Any ideas what could be wrong?
What scope does your ManagedBean have?
When you use a RequestScope you are not able to submit your selectOneMenu with an UICommand component like p:commandLink when you set the ajax attribute to false. The changes are lost in this case.
Here are two possibilities to fix your problem:
Attempt 1: Set your Bean ViewScoped:
In most cases this will work. If you must use special annotations to annotate your beans (like Apache DeltaSpike #ViewAccessScoped for example), try to separate your bean into View and Controller beans, annotating the View with just simple #ViewScope and keeping all the values in it.
Attempt 2: Remove ajax="false" from p:commandLink:
This will work if your use-case allows it. For example, downloading a file with PrimeFaces will require explicit declaration that the ajax is not to be used, so this solution will not be applicable.
add ajax listener
<h:selectOneMenu value="#{Region.dropDownValue}" id="dropDown">
<f:selectItem itemLabel="" itemValue=""/>
<f:selectItem itemLabel="1" itemValue="1"/>
<f:selectItem itemLabel="2" itemValue="2"/>
<f:selectItem itemLabel="3" itemValue="3"/>
<f:selectItem itemLabel="4" itemValue="4"/>
<p:ajax event="change" update="#this"/>
</h:selectOneMenu>

Primefaces valueChangeListener or <p:ajax listener not firing for p:selectOneMenu [duplicate]

This question already has answers here:
commandButton/commandLink/ajax action/listener method not invoked or input value not set/updated
(12 answers)
Closed 7 years ago.
I am using Primefaces 3.4.2.
I have the following in my JSF page
<p:selectOneMenu id="emp" value="#{mymb.emp.employeeName}"
valueChangeListener="#{mymb.handleChange}"
required="true"
style="width: 150px;">
<f:selectItem noSelectionOption="true"
itemLabel="Please Select"/>
<f:selectItems value="#{mymb.employeeList}" var="emp"
itemLabel="#{emp.employeeName}"
itemValue="#{emp.employeeNumber}"/>
<p:ajax update="sublist"/>
</p:selectOneMenu>
and in ManagedBean
public void handleChange(ValueChangeEvent event){
System.out.println("here "+event.getNewValue());
}
The problem is valueChangeListener is not firing, i.e. handleChange method is not getting invoked. I tried with the following, but it is not working either.
<p:ajax update="sublist" listener="#{mymb.handleChange}" />
Separate JSF page:
<ui:composition template="/templates/layout.xhtml"
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">
<ui:define name="content">
<h:head>
</h:head>
<h:body>
<h:form id="form">
<p:panelGrid columns="6">
<h:outputLabel value="Employees" for="employees" />
<p:selectOneMenu id="employees"
value="#{mymb.employeesList}"
required="true">
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" />
<p:ajax listener="#{mymb.handleChange}" />
</p:selectOneMenu>
</p:panelGrid>
</h:form>
</h:body>
</ui:define>
</ui:composition>
If you want to use valueChangeListener, you need to submit the form every time a new option is chosen. Something like this:
<p:selectOneMenu value="#{mymb.employee}" onchange="submit()"
valueChangeListener="#{mymb.handleChange}" >
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeID}" />
</p:selectOneMenu>
public void handleChange(ValueChangeEvent event){
System.out.println("New value: " + event.getNewValue());
}
Or else, if you want to use <p:ajax>, it should look like this:
<p:selectOneMenu value="#{mymb.employee}" >
<p:ajax listener="#{mymb.handleChange}" />
<f:selectItems value="#{mymb.employeesList}" var="emp"
itemLabel="#{emp.employeeName}" itemValue="#{emp.employeeID}" />
</p:selectOneMenu>
private String employeeID;
public void handleChange(){
System.out.println("New value: " + employee);
}
One thing to note is that in your example code, I saw that the value attribute of your <p:selectOneMenu> is #{mymb.employeesList} which is the same as the value of <f:selectItems>. The value of your <p:selectOneMenu> should be similar to my examples above which point to a single employee, not a list of employees.
The valueChangeListener is only necessary, if you are interested in both the old and the new value.
If you are only interested in the new value, the use of <p:ajax> or <f:ajax> is the better choice.
There are several possible reasons, why the ajax call won't work. First you should change the method signature of the handler method: drop the parameter. Then you can access your managed bean variable directly:
public void handleChange(){
System.out.println("here "+ getEmp().getEmployeeName());
}
At the time, the listener is called, the new value is already set. (Note that I implicitly assume that the el expression mymb.emp.employeeName is correctly backed by the corresponding getter/setter methods.)
Another solution is to mix valueChangeListener, ajax and process:
<p:selectManyCheckbox id="employees" value="#{employees}" columns="1" layout="grid" valueChangeListener="#{mybean.fireSelection}" >
<f:selectItems var="employee" value="#{employeesSI}" />
<p:ajax event="valueChange" immediate="true" process="#this"/>
</p:selectManyCheckbox>
Method in mybean is just :
public void fireSelection(ValueChangeEvent event) {
log.debug("New: "+event.getNewValue()+", Old: "+event.getOldValue());
}
Like this, valueChangeEvent is very light !
PS: Works fine with PrimeFaces 5.0
<p:ajax listener="#{my.handleChange}" update="id of component that need to be rerender after change" process="#this" />
import javax.faces.component.UIOutput;
import javax.faces.event.AjaxBehaviorEvent;
public void handleChange(AjaxBehaviorEvent vce){
String name= (String) ((UIOutput) vce.getSource()).getValue();
}
All can be defined as in f:ajax attiributes.
i.e.
<p:selectOneMenu id="employees" value="#{mymb.employeesList}" required="true">
<f:selectItems value="#{mymb.employeesList}" var="emp" itemLabel="#{emp.employeeName}" />
<f:ajax event="valueChange" listener="#{mymb.handleChange}" execute="#this" render="#all" />
</p:selectOneMenu>
event: it can be normal DOM Events like click, or valueChange
execute: This is a space separated list of client ids of components that will participate in the "execute" portion of the Request Processing Lifecycle.
render: The clientIds of components that will participate in the "render" portion of the Request Processing Lifecycle. After action done, you can define which components should be refresh. Id, IdList or these keywords can be added: #this, #form, #all, #none.
You can reache the whole attribute list by following link:
http://docs.oracle.com/javaee/6/javaserverfaces/2.1/docs/vdldocs/facelets/f/ajax.html
Try using p:ajax with event attribute,
My problem were that we were using spring securyty, and the previous page doesn't call the page using faces-redirect=true, then the page show a java warning, and the control doesn't fire the change event.
Solution:
The previous page must call the page using, faces-redirect=true
this works for me:
It can be used inside the dialog, but the dialog canĀ“t be inside any componet such as panels, accordion, etc.

valuechangelistener does not populate values in text box

Here is my jsp:
<h:selectOneMenu value="#{member.dependentName}" onchange="this.form.submit()"
immediate="true" valueChangeListener="#{member.getDependentAddress}">
<f:selectItems value="#{member.dependentList}" />
</h:selectOneMenu>
<h:inputText value="#{member.personName}" immediate="true" />
<h:inputText value="#{member.dob}" immediate="true" />
And this, the function valuechangelistener fires.
public void getDependentAddress(ValueChangeEvent e) {
setPersonName((getDependentsList().get(e.getNewValue().toString())
.getDependentName()));
setDob(getDependentsList().get(e.getNewValue().toString()).getBirth());
System.out.println("New dob value : " + dob);
System.out.println("New name value : " + personName);
FacesContext.getCurrentInstance().renderResponse();
}
The two sysouts give the new value in the console but once the page loads, the fields are blank. I have tried all scopes for the bean. No go. What am i missing?
Thanks
You missed nothing. You've just something too much. To get it to work, you should remove immediate="true" from the to-be-changed components.
<h:selectOneMenu value="#{member.dependentName}" onchange="this.form.submit()"
immediate="true" valueChangeListener="#{member.getDependentAddress}">
<f:selectItems value="#{member.dependentList}" />
</h:selectOneMenu>
<h:inputText value="#{member.personName}" />
<h:inputText value="#{member.dob}" />
The immediate="true" on an UIInput component will cause its validations phase to take place in apply request values phase instead. This gives you the opportunity to use FacesContext#responseComplete() inside a valueChangeListener method skip other components which doesn't have immediate="true" set from being processed. As you have now, with immediate="true", they are also processed.
Please note that this is essentially a hack from the old JSF 1.x ages. If you're already using JSF 2.x, you should be using <f:ajax listener> instead.
<h:selectOneMenu value="#{member.dependentName}">
<f:selectItems value="#{member.dependentList}" />
<f:ajax listener="#{member.getDependentAddress}" render="name dob" />
</h:selectOneMenu>
<h:inputText id="name" value="#{member.personName}" />
<h:inputText id="dob" value="#{member.dob}" />
with
public void getDependentAddress() {
Dependent dependent = getDependentsList().get(dependentName); // Isn't that actually a Map instead of List?
personName = dependent.getDependentName();
dob = dependent.getBirth();
}

Jsf redirect to new window

i'm making a JSF2.0 project using mojarra primefaces tomcat6.x.
I made a select list and when i select item of the list i want to redirect to the selected url. It can be an internal URL.
It's work but i want to know if it's possible to redirect in new window.
I have the following code JSF:
<h:form>
<h:selectOneMenu onchange="this.form.submit();" valueChangeListener="#{wagent.selectBusinessTravelLink}">
<f:selectItem itemLabel="#{msg['form.select.defaultValue']}" itemValue="" noSelectionOption="true"/>
<f:selectItems value="#{wagent.businessTravelLinks}" var="bLinkItem" itemLabel="#{bLinkItem.label}" itemValue="#{bLinkItem.id}" />
</h:selectOneMenu>
</h:form>
Java:
public void selectBusinessTravelLink(ValueChangeEvent event) {
// some stuff
FacesContext.getCurrentInstance().getExternalContext().redirect(targetUrl);
}
Use JavaScript's window.open() function rather than form.submit() during the change event.
Assuming that the select item values are fullworthy URL's, here's an example:
<h:selectOneMenu onchange="window.open(this.options[this.selectedIndex].value)">
Use onclick="this.form.target='_blank'" (or in your case in onchange), i.e.,
<h:form id="form">
<h:selectOneMenu onchange="this.form.target='_blank'; this.form.submit();" valueChangeListener="#{wagent.selectBusinessTravelLink}">
<f:selectItem itemLabel="#{msg['form.select.defaultValue']}" itemValue="" noSelectionOption="true"/>
<f:selectItems value="#{wagent.businessTravelLinks}" var="bLinkItem" itemLabel="#{bLinkItem.label}" itemValue="#{bLinkItem.id}" />
</h:selectOneMenu>
</h:form>
And of course, don't forget to fix the id attribute in <h:form id="form">

Resources