Add selectedValue from selectonemenu to list - jsf

So, here's the deal:
I have a selectOneMenu in my view:
<p:selectOneMenu value="#{personBean.person.personStates.state}" id="estadoRg"
converter="entityConverter">
<f:selectItems value="#{stateBean.states}" var="state"
itemLabel=#{state.name}" itemValue="#{state}">
</f:selectItems>
</p:selectOneMenu>
Where personStates is a list containing person, state n date.
Is it possible to add the value from the itemValue directly to the personStates list? (I have a addPersonState method autobuilt in my PersonModel)
If not, how should I do this?
I don't want to add one state instance for each selectOneMenu (will be 5) in my personBean...
Was it clear?

You should handle it via selectedState value and then you can bind it for specific person:
<p:selectOneMenu value="#{stateBean.selectedState}" id="estadoRg"
converter="entityConverter">
<f:selectItems value="#{stateBean.states}" var="state"
itemLabel=#{state.name}" itemValue="#{state}">
</f:selectItems>
</p:selectOneMenu>
This is the way how p:selectOneMenu is used, to be able to bind selected state and the person call a method:
<p:commandButton actionListener="#{personBean.matchStates}" />
And backing bean method:
public void matchStates {
FacesContext facesContext = FacesContext.getCurrentInstance();
ElContext elContext = facesContext.getELContext();
Object stateBean = elContext.getELResolver().getValue(elContext, null, "stateBean").
State selectedState = stateBean.getSelectedState();
personList.get(index).setState = selectedState;
}

Related

How to use ajax with Primefaces components programmatically

I'm trying to create Primefaces UIComponents programmatically and somehow I'm not able to get the data to the Backing Bean. Not sure if it's the Ajax or the value I set for the InputText.
My code that I want to write programmatically:
<p:inputText id="id_test" value="#{myBean.value}">
<p:ajax />
</p:inputText>
This is how I tried to solve the problem:
private String value; // Getter&Setter
public void buildComponent(){
FacesContext fc = FacesContext.getCurrentInstance();
Application ap = fc.getApplication();
InputText inputText = (InputText) ap.createComponent(fc, "org.primefaces.component.InputText", "org.primefaces.component.InputTextRenderer")
inputText.setValue(value);
inputText.setId("id_test");
AjaxBehavior ajaxBehavior = (AjaxBehavior) ap.createBehavior(AjaxBehavior.BEHAVIOR_ID);
inputText.addClientBehavior(inputText.getDefaultEventName(), behavior);
}
You will need to create a ValueExpression that resolves to your bean property. How else should your dynamic input know where to send input values to?
Instead of:
inputText.setValue(value);
Do this:
ExpressionFactory expressionFactory = FacesContext.getCurrentInstance()
.getApplication().getExpressionFactory();
ValueExpression veBinding = expressionFactory.createValueExpression("#{myBean.value}", String.class);
inputText.setValueExpression("value", veBinding);
I'm not sure what you intend to do, but it might be better to render the component dynamically instead of creating it. Something like that:
<p:inputText id="id_test" value="#{myBean.value}" rendered="#{myBean.isSomeCondition">
<p:ajax />
</p:inputText>
or
<p:inputText id="id_test" value="#{myBean.value}" rendered="#{myBean.value != 'whatever'">
<p:ajax />
</p:inputText>

jsf selectOneMenu value does not change

I have a selectOneMenu that have the correct values (a list of string) however when I select a value it does not trigger the setSelectedValue from the bean.
<h:selectOneMenu layout="lineDirection" id="myMenu" value="#{dwrBean.selectedValue}">
<f:selectItems value="#{Bean.values}"/>
</h:selectOneMenu>
Bean:
private String selectedValue = "";
private List<String> values = new LinkedList<String>();
...
public String getSelectedValue() {
return this.selectedValue;
}
public void setSelectedValue(String selectedValue) {
LOGGER.debug("Try to set selected value" + selectedValue);
if (!selectedValue.isEmpty()){
this.selectedValue = selectedValue ;
}
}
There is nothing in the logs.
I've tried to add a listener:
<h:selectOneMenu layout="lineDirection" id="myMenu" value="#{dwrBean.selectedValue}" valueChangeListener="#{dwrBean.statusChanged}" >
<f:selectItems value="#{dwrBean.values}"/>
</h:selectOneMenu>
Here the statusChanged is triggered but the newValue is null, the oldValue is correct, but it is always the same.
public void statusChanged(ValueChangeEvent event) {
LOGGER.debug("new" + event.getNewValue());
LOGGER.debug("old" + event.getOldValue());
if (event.getNewValue() != null &&
!((String) event.getNewValue()).isEmpty()) {
LOGGER.debug("OK");
}
}
I really don't understand.
Actually the selectOneMenu is within a popup.
I've moved the selectOneMenu outside of the popup and it works. Do I have to change the scope of the Bean ?
Non-working configuration:
<h:form>
<rich:popupPanel>
<h:selectOneMenu>
...
</h:selectOneMenu>
<rich:popupPanel>
<h:form>
Working configuration:
<h:form>
<h:selectOneMenu>
...
</h:selectOneMenu>
<rich:popupPanel>
<rich:popupPanel>
<h:form>
below method invoke when you subbmit form
public void setSelectedValue(String selectedValue) {
LOGGER.debug("Try to set selected value" + selectedValue);
if (!selectedValue.isEmpty()){
this.selectedValue = selectedValue ;
}
}
You need to use AJAX to do a partial form submission when the value changes. The valueChangeListener is a hook that provides your code with notification when the value has changed and the form has been submitted.
The code below will register an AJAX event for the onchange event for selectOneMenu. The value changes it will then execute the menu (submit the value to the bean).
<h:selectOneMenu layout="lineDirection" id="myMenu" value="#{dwrBean.selectedValue}">
<f:selectItems value="#{dwrBean.values}"/>
<f:ajax/>
</h:selectOneMenu>

Add a new p:SelectOneMenu to a JSF page dynamically from the Backing bean

i want to add dynamically an new p:SelectOneMenu to my panelGrid here
<h:panelGrid id="panel_grid" columns="1" style="margin-bottom:10px"cellpadding="5" >
<p:outputLabel for="firstQuestionDropDown" value={InsererAffaireController.firstQuestion.libeleQuestion}"
<p:selectOneMenu id="firstQuestionDropDown" value="#{InsererAffaireController.firstQuestion.libeleQuestion}" style="width:150px">
<p:ajax listener="#{InsererAffaireController.displayNextQuestion()}" update="panel_grid" />
<f:selectItems value="#{InsererAffaireController.firstQuestion.listLibeleReponses}" />
</p:selectOneMenu>
<!-- Here i want to add my new SelectOneMenu -->
</h:panelGrid>
I managed to do that from the managed bean but the problem is that i can't populate the new SelectOneMenu and i don't know how to add a f:selectItems to it
here is the method that add the new p:SelectOneMenu to the panel grid but it still empty
public void displayNextQuestion() {
nextQuestion = getNextQuestion();
OutputLabel nextQuestionLabelUI = new OutputLabel();
nextQuestionLabelUI.setValue(nextQuestion.getLibeleQuestion());
SelectOneMenu nextQuestionDropDown = new SelectOneMenu() ;
List<SelectItem> selectItems = new ArrayList<>();
for (String s : nextQuestion.getListLibeleReponses()) {
selectItems.add(new SelectItem(s, s));
System.out.println(selectItems.get(0).getLabel());
}
// How can i add the selectitems to the SelectOneMenu
UIComponent panelGrid = findComponent("panel_grid");
panelGrid.getChildren().add(nextQuestionLabelUI);
panelGrid.getChildren().add(nextQuestionDropDown) ;
RequestContext.getCurrentInstance().update("panel_grid");
}
You can use the UISelectItems class like this:
...
UISelectItems selectItemsComponent = new UISelectItems();
selectItemsComponent.setValue(selectItems);
nextQuestionDropDown.getChildren().add(selectItemsComponent);
...

<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}" />

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>

Resources