JSF- passing a parameter to valuechangelistener - jsf

I have a litte radiobutton like this :
<h:selectOneRadio value="#{test.answer}" valueChangeListener="#{TestService.changeanswer}" immediate="true" id="answer">
<f:selectItem itemValue="A" itemLabel="Absolutely True"/>
<f:selectItem itemValue="B" itemLabel="True"/>
<f:selectItem itemValue="C" itemLabel="Partially True"/>
<f:selectItem itemValue="D" itemLabel="Not True"/>
<f:selectItem itemValue="E" itemLabel="Definitely Not True"/>
<f:ajax event="change" process="answer"></f:ajax></h:selectOneRadio>
And my listener is like that :
public void changeanswer(ValueChangeEvent vcEvent) {
System.out.println("comeon= " + vcEvent.getOldValue());
System.out.println("comeon= " + vcEvent.getNewValue());}
I would like to pass a parameter to the changeanswer method.For example I want to pass the questionid to the changeanswer function. I need to make some arrangements in it.
How can I do that?
Many many many thanks in advance.
Brad - the Rookie..

You can use the f:attribute tag to send any data to the ValueChangeListener:
<h:selectOneRadio value="#{test.answer}"
valueChangeListener="#{TestService.changeanswer}"
immediate="true" id="answer">
<f:attribute name="myattribute" value="#{test.questionid}" />
<f:selectItem itemValue="A" itemLabel="Absolutely True"/>
...
</h:selectOneRadio>
If we suppose questionId is an Integer, then you can receive the data the following way:
public void changeanswer(ValueChangeEvent vcEvent) {
Integer questionId =
(Integer) ((UIInput) vcEvent.getSource()).getAttributes().get("myattribute");

Seeing how the component values are bound, I bet that it's inside a datatable. If that is indeed the case, you can use DataModel#getRowData() to obtain the current row. Add a DataModel property to the TestService bean like follows:
private List<Question> questions;
private DataModel<Question> questionModel;
#PostConstruct
public void init() {
questions = getItSomehow();
questionModel = new ListDataModel<Question>(questions);
}
public void change(ValueChangeEvent event) {
Question currentQuestion = questionModel.getRowData();
// ...
}
and change the view as follows:
<h:dataTable value="#{TestService.questionModel}" var="test">
That said, I'd suggest to use more sensible variable names than TestService, test and change(), like Questionaire, question and changeAnswer() respectively. This makes the code more self-documenting.

Related

can't access to suffixs or enum's values in primefaces <p:selectOneMenu component.. any solution?

Hi I am currently working on a java project (jsf) with primefaces and I am using enum, but I cannot access its values from the view with primefaces. I have temporarily solved the problem by creating a getter from the Bean and accessing the enum values, but it should work with allSuffix = "ALL_ENUM_VALUES" or ALL_VALUES by default, I don't know if it's a problem with primefaces, joinfaces or something I'm missing. I have looked into the official documentation and it should work... any solution?
my code is
<p:importEnum
type="com.path.enumeration.AltoMedioBajo"
var="AltoMedioBajo"
allSuffix="ALL_ENUM_VALUES" />
<p:outputLabel
for="posibilidad"
value="#{informe_msg.posibilidad}" />
<p:selectOneMenu
id="posibilidad"
style="width: 150px"
value="#{informeSeguimientoDto.specification.posibilidad}">
<f:selectItem
itemLabel=""
itemValue="" />
<f:selectItems
value="#{AltoMedioBajo.ALL_ENUM_VALUES}"
var="posibilidad"
itemValue="#{posibilidad}"
itemLabel="#{peticion_msg[posibilidad.femKey]}" />
</p:selectOneMenu> ```
Hi this question was answered here: How to use enum values in f:selectItem(s)
With joinfaces I tested this example:
User Bean
#Named
#ApplicationScoped
public class UserBean {
public Role[] getRoles() {
return Role.values();
}
}
add_user.xhtml
<p:selectOneMenu id="roleId" value="#{userBean.newUser.roleId}">
<f:selectItem itemValue="" itemLabel=""/>
<f:selectItems value="#{userBean.roles}" var="role" itemValue="#{role.getId()}" itemLabel="#{messages['role_' += role]}"/>
</p:selectOneMenu>
Role Enum with custom order, it's not mandatory you can use default .ordinal() value
public enum Role {
ASSISTANT(1),
ACCOUNTANT(4),
CASHIER(5),
ADMIN(10);
private final int id;
Role(int id) {
this.id = id;
}
public int getId() {
return id;
}
// method to get the Role using Id from the database
public static Role valueOf(int id) {
return Arrays.stream(values())
.filter(role -> role.id == id)
.findFirst()
.orElse(null);
}}
messages_es.properties as Resource Bundle
role_ASSISTANT=Asistente
role_ACCOUNTANT=Contador
role_CASHIER=Cajero
role_ADMIN=Administrador
As per documentation/demo, you should use a repeat tag.
Edited: Try this version:
<p:importEnum type="com.path.enumeration.AltoMedioBajo" var="AltoMedioBajo"
allSuffix="ALL_ENUM_VALUES" />
<p:outputLabel for="posibilidad" value="#{informe_msg.posibilidad}" />
<p:selectOneMenu id="posibilidad" style="width: 150px"
value="#{informeSeguimientoDto.specification.posibilidad}">
<f:selectItem />
<ui:repeat var="posibilidad" value="#{AltoMedioBajo.ALL_ENUM_VALUES}">
<f:selectItem itemValue="#{posibilidad}"
itemLabel="#{peticion_msg[posibilidad.femKey]}"
</ui:repeat>

<f:selectItems is not returning value in <p:selectOneMenu>

I have a problem with getting value of f:selectItems but it is returning its label.
here is the code;
<p:selectOneMenu>.
<p:outputLabel value="Major Diseases"></p:outputLabel>
<p:selectOneMenu value="#{dataMigeration.mdId}">
<f:selectItem itemLabel="Select One" itemValue="" />
<f:selectItems var="t"
value="#{dataMigeration.majorDiseas}"
itemLabel="#{t.value.mdName}"
itemValue="#{t.value}"/>
<p:ajax listener="#{dataMigeration.getSubDiseasesByMojarDisease(dataMigeration.mdId)}"
event="change" update="dataMigration"/>
</p:selectOneMenu>
here is the dataMigeration class
#ManagedBean(name="dataMigeration")
#SessionScoped
public class DataMigeration{
String mdId;
private List<SelectItem> majorDiseas = new ArrayList<SelectItem>();
public List<SelectItem> getMajorDiseas() {
majorDiseas = new ArrayList<SelectItem>();
System.out.println("DataMigeration.getMajorDiseas():");
List<DiseaseCategory> majorDiseasesList = new ArrayList<DiseaseCategory>();
majorDiseasesList=DataManager.findAllRecords();
for (DiseaseCategory obj : majorDiseasesList) {
majorDiseas.add(new SelectItem(obj.getMdId(), obj.getMdName()));
}
return majorDiseas;
}
public void getSubDiseasesByMojarDisease(String mdId)
{
System.out.println("\n\n\n\n | value:"+mdId);
}
but I am getting mdId=itemLabel of f:selectedItem but I want to get itemValue of f:selectem. SomeWhere I have done before but I forgot now how to get ItemValue.
Your 'f:selectItems' statement is wrong. You can use the 'var' attribute to loop through a list of complex Java objects to dynamically create a list of SelectItem objects. (See http://www.mkyong.com/jsf2/jsf-2-dropdown-box-example/ for examples)
But in this case, you've already created your list of SelectItem objects in the backing bean, so just reference it like this instead:
<f:selectItems value="#{dataMigeration.majorDiseas}" />

primefaces selectOneMenu how to reload

I use 3 selectOneMenu components in my project. I need to reload content of the second after change in the first. Here are some parts of the files
index.xhtml
<h:form id="form">
<p:selectOneMenu id="Rząd" value="#{birdSelectorBean.selectedState}" effect="fade"
style="width: 150px;">
<f:selectItem itemLabel="Rząd" itemValue="" />
<f:selectItems value="#{birdSelectorBean.rzad}" />
<p:ajax render="#form" listener="#{birdSelectorBean.stateChangeListener}" />
</p:selectOneMenu>
<p:selectOneMenu id="rodzina" value="#{birdSelectorBean.selectedState}" effect="fade"
style="width: 150px;">
<f:selectItem itemLabel="Rodzina" itemValue="" />
<f:selectItems value="#{birdSelectorBean.rodzina}" />
</p:selectOneMenu>
<p:selectOneMenu id="rodzaj" value="#{birdSelectorBean.selectedState}" effect="fade"
style="width: 150px;">
<f:selectItem itemLabel="Rodzaj" itemValue="" />
<f:selectItems value="#{birdSelectorBean.rodzaj}" />
</p:selectOneMenu>
</h:form>
BirdSelectionBean.java:
public class BirdSelectorBean
{
private String selectedState;
private List<SelectItem> rzad;
private List<SelectItem> rodzina;
private List<SelectItem> rodzaj;
public BirdSelectorBean()
{
rzad = new ArrayList<>();
rzad.add(new SelectItem("Rząd_X"));
rzad.add(new SelectItem("Rząd_Y"));
rzad.add(new SelectItem("Rząd_Z"));
rodzina = new ArrayList<>();
rodzaj = new ArrayList<>();
}
public void stateChangeListener(ValueChangeEvent event)
{
rodzina.clear();
rodzina.add(new SelectItem("Rodzina_A"));
rodzina.add(new SelectItem("Rodzina_B"));
rodzina.add(new SelectItem("Rodzina_C"));
}
...
getters and setters
...
}
I read many topics on that but it doesn't work for me. I tried update="rodzina" like it is in example
here
and render option like it is said in that
topic:
But it still doesn't work. Please help me :]
In the p:ajax tag change render="#form" to update="#form". Render is used by f:ajax, primefaces use another name for some reason - see here.
Looks like your stateChangeListener method nevers get called and more important, your managed bean looks like hasn't any scope (at least from your question content), remember that it must be at least #ViewScoped in order to make this work. Also, another problem in your code is that you're using the same attribute to select the data for the three <p:selectOnuMenu> (which is not a problem yet since you haven't achieved what you wanted to begin with).
To make the ajax update work, remove the parameter from your stateChangeListener. Also let's add the other two attributes for the selected items from the dropdownlists.
#ManagedBean
#ViewScoped
public class BirdSelectorBean {
private String selectedState;
private String selectedStateRodzina;
private String selectedStateRodzaj;
//other fields and methods...
public void stateChangeListener() {
rodzina.clear();
rodzina.add(new SelectItem("Rodzina_A"));
rodzina.add(new SelectItem("Rodzina_B"));
rodzina.add(new SelectItem("Rodzina_C"));
}
}
And then update your desired <p:selectOneMenu> in your <p:ajax> call (I removed the non-directly related to the problem attributes from the components like style):
<p:selectOneMenu id="Rząd" value="#{birdSelectorBean.selectedState}">
<f:selectItem itemLabel="Rząd" itemValue="" />
<f:selectItems value="#{birdSelectorBean.rzad}" />
<p:ajax update="rodzina" listener="#{birdSelectorBean.stateChangeListener}" />
</p:selectOneMenu>
<p:selectOneMenu id="rodzina" value="#{birdSelectorBean.selectedStateRodzina}">
<f:selectItem itemLabel="Rodzina" itemValue="" />
<f:selectItems value="#{birdSelectorBean.rodzina}" />
</p:selectOneMenu>

Cascading p:selectOneMenu fails with Validation Error: Value is not valid [duplicate]

This question already has answers here:
Validation Error: Value is not valid
(3 answers)
Closed 7 years ago.
I have two cascading p:selectOneMenu components. The first shows areas from a hashmap and the second shows cities for the selected area by ajax. But when submitting the form with the city selected, I get
Validation Error: Value is not valid
Here's the view
<p:selectOneMenu id="area" value="#{bean.area}">
<f:selectItem itemLabel="Select Area" itemValue="" />
<f:selectItems value="#{bean.areas}" />
<p:ajax update="city" listener="#{bean.handleAreaChange()}" />
</p:selectOneMenu>
<p:selectOneMenu id="city" value="#{bean.city}">
<f:selectItem itemLabel="Select City" itemValue="" />
<f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>
Here's the bean:
private String area;
private String city;
private Map<String, String> areas = new HashMap<String, String>();
private Map<String, String> cities = new HashMap<String, String>();
private Map<String, Map<String, String>> allCities = new HashMap<String, Map<String,String>>();
public void handleAreaChange() {
if (area != null && !area.isEmpty()) {
cities = allCities.get(area);
} else {
cities = new HashMap<String, String>();
}
}
How is this caused and how can I solve it?
You will get this error when the submitted value of the dropdown is not contained in the list of available values. So this means that the list of available values has incompatibly changed during the HTTP request of the form submit as compared to the HTTP request of displaying the form. This in turn often means that the backing bean is request scoped and that the list of available values is not preinitialized in its (post)constructor.
Either putting the bean in the view scope, or adding code which properly preinitializes the list of available values based on request parameters, should fix your problem.
As BalusC said the value (identifier) of the selectItem has changed. This can happen if your bean is request scoped or if the objects have changed server side.
A common solution I use is to set the value of the selectItem to an id of the object it represents.
Lets assume City and Area have unique identifiers (id) and looks like this:
public class City //or Area
{
private Long id;
private String name;
//Rest of class
}
You can then introduce a converter for City and Area:
#FacesConverter("cityConverter")
public class CityConverter implements javax.faces.convert.Converter
{
#Override
public Object getAsObject(FacesContext ctx, UIComponent cmp, String str)
{
//Convert id to Object (City) and return it
}
#Override String getAsString(FacesContext ctx, UIComponent, Object obj)
{
//Return the id that represents the Object (City) here
return ((City)obj).getId().toString();
}
}
In your JSF page make use of the converter:
<p:selectOneMenu id="area" value="#{bean.area}" converter="areaConverter">
<f:selectItem itemLabel="Select Area" itemValue="" />
<f:selectItems value="#{bean.areas}" />
<p:ajax update="city" listener="#{bean.handleAreaChange()}" />
</p:selectOneMenu>
<p:selectOneMenu id="city" value="#{bean.city}" converter="cityConverter">
<f:selectItem itemLabel="Select City" itemValue="" />
<f:selectItems value="#{bean.cities}" />
</p:selectOneMenu>
More about how to implement a FacesConverter on this site.
The first thing you need to do is to tell link the ajax to an event. So you probably want it to happen on the valueChange event so your ajax should be:
<p:ajax update="tmil2" event="valueChange" listener="#{BeanAreaAndCity.handleCityChange()}"></p:ajax>

How to set default value of h:selectOneRadio button

I am unable to set the default value of h:selectOneRadio as i need radio button to be pre selected
<h:selectOneRadio id="myRadio" value="#{Externalbean.addressFlag}" >
<f:selectItem itemValue="1" itemLabel="Yes"/>
<f:selectItem itemValue="0" itemLabel="No"/>
</h:selectOneRadio>
and my backing bean is
private String addressFlag="0";
public String getAddressFlag() {
return addressFlag;
}
public void setAddressFlag(String addressFlag) {
this.addressFlag = addressFlag;
}
but no luck
You need to set the default value in the init method of your backing bean:
#ManagedBean
public class YourBackingBean implements Serializable {
private String addressFlag;
#PostConstruct
public void init() {
addressFlag = "0";
}
public String getAddressFlag() {
return addressFlag;
}
public void setAddressFlag(String addressFlag) {
this.addressFlag = addressFlag;
}
}
I did a little test, it works just fine as expected, but I also observed that when you leave out the <h:form> tag, the behaviour of radio buttons is unpredictable and dependent on the webbrowser. The JSF-generated HTML output looks correct, but the webbrowser would in the view only select the button which was actually selected by the user in the previous request on the same page. If the cache is empty, none of the buttons is selected. At least, that was the case in FF.
So, it look like that you have forgotten to put a <h:form> around it.
Only use that <h:selectOneRadio required="true"> :
<h:selectOneRadio required="true" id="myRadio" value="#{Externalbean.addressFlag}" >
<f:selectItem itemValue="1" itemLabel="Yes"/>
<f:selectItem itemValue="0" itemLabel="No"/>
</h:selectOneRadio>
Did you try to set the addressFlag as an Integer?
private Integer addressFlag = 0;
public Integer getAddressFlag() {
return addressFlag;
}
public void setAddressFlag(Integer addressFlag) {
this.addressFlag = addressFlag;
}

Resources