Submitting ID of object-populated h:selectOneMenu still causes conversion error - jsf

I populated my selectOneMenu with objects and trying to send the id (in itemValue) back to my bean from the selected item, I tried it using the below functionality but I keep getting error about a null converter (Which I'm trying to avoid by sending the id to my bean).
xhtml:
<h:form>
<h:selectOneMenu value="#{bean.id}">
<f:selectItems value="#{bean.objectList}" var="f" itemValue="#{f.id}" itemLabel="#{f.name}" />
</h:selectOneMenu>
<h:commandButton action="#{bean.function}" value="OK"/>
</h:form>
bean:
private Collection<Object> objectList; //Object is an example, It is not the real class that is used
private int id;
public void function() {
// place where id is needed.
}
// id getters & setters

The collection you are using:
private Collection<Object> objectList;
Has a plain object as the class type for its elements.
You need to change it to:
private Collection<MyCustomClassElement> objectList;
Where MyCustomClassElement is the class for your collection elements used in the select.

I think the value is not updated, use ajax to update the value once you select it...
<h:form id="forms">
<h:selectOneMenu id="beanid" value="#{bean.id}">
<f:selectItems value="#{bean.objectList}" var="f" itemValue="#{f.id}" itemLabel="#{f.name}" />
<f:ajax event="change" render="forms" />
</h:selectOneMenu>
<h:commandButton action="#{bean.function}" value="OK"/>
</h:form>

Related

How to pass the selected values from selectcheckBoxMenu to my bean?

I'm using JSF 2.2.8 and primefaces 6.0, and i have a selectCheckBoxMenu i want to retrieve the selected values in my bean.
The selectCheckboxMenu is filled from the database but when i select the attributes and I save nothing happens it does not call the save function
Here is my selectCheckBoxMenu
<p:outputLabel for="ressource" value="Ressource"/>
<h:panelGroup >
<p:selectCheckboxMenu id="ressource" label="Ressource" value="#{affectationBean.selectedRessource}" multiple="true">
<f:selectItems value="#{affectationBean.ressources}" var="r" itemLabel="#{r.nom}" itemValue="r.idt_ressource" />
</p:selectCheckboxMenu>
</h:panelGroup>
<p:commandButton icon="ui-icon-save" actionListener="#{affectationBean.save}" value="Save" update="#affectation" ajax="false" style="display:inline-block;margin-top:5px"/>
Here is the the declaration of the selectedRessource and the actionListener save
private Long [] selectedRessource;
// Getters setters and Construct
public void save(){
for(int i=0 ;i<selectedRessource.length;i++){
system.out.println("id ===> " + selectedRessource[i]);
}
My suggestion would be:
First make sure everything is inside the h:form tag.
don't need to multiple = true as this tag does not take this attribute
i tested with below modification and got the selected multiple value in my bean. The only difference is i am using same value for itemLabel and itemValue but in your case it is object. i am using primefaces 6 also and dont even need to change actionListner to action. It is working as it is.sample xhtml
sample ResourceBean.java
<p:outputLabel for="ressource" value="Ressource"/>
<h:panelGroup >
<p:selectCheckboxMenu id="ressource" label="Ressource" value="#{resourceBean.selectedRessource}">
<f:selectItems value="#{resourceBean.ressources}" var="r" itemLabel="#{r}" itemValue="#{r}" />
</p:selectCheckboxMenu>
</h:panelGroup>
<p:commandButton icon="ui-icon-save" actionListener="#{resourceBean.save}" value="Save" ajax="false" style="display:inline-block;margin-top:5px"/>
The problem is in your p:commandButton, you have 3 options
change your method:
public void save(ActionEvent actionEvent){...}
change your action listener value:
actionListener="#{affectationBean.save()}"
or change your button to use action
action="#{affectationBean.save}"
DISCLAIMER: This is a workaround. It is not intended to be a permanent solution but will allow you to use selectCheckboxMenu and keep working.
There is an issue with this component that prevents it from passing values to the backing bean upon submit.
For some reason the array that should contain the selected values gets cleared out upon submit. Therefore I made an extra array that I did not declare in the tag, and updated in on every change event. Then on submit the values were still there. See below:
BackingBean.java
private String[] sCodes;
private String[] sCodes2; //extra array, not in form.xhtml
public void updateCodes()
{
sCodes2 = sCodes; //keeps the values in the other array
}
public void doSend() throws IOException
{
log.trace("selected codes: {} selected codes2 length: {}", sCodes.length, sCodes2.length);
}
form.xhtml
<p:selectCheckboxMenu id="codeCtl" value="#{bean.SCodes}" label="Codes" filter="true" filterMatchMode="startsWith" panelStyle="width:250px">
<f:selectItems value="#{bean.menuCodes}" />
<p:ajax event="change" listener="#{bean.updateCodes()}" />
</p:selectCheckboxMenu>
<p:commandButton value="submit" actionListener="#{bean.doSend}" id="ctlSubmit" update="appform"/>

How to insert PrimeFaces p:selectManycheckbox value to database

I am new to primefaces and i have a problem to save my primefaces SelectManyCheckbox value to database. I am using hibernate and mysql. The sample code are give as below
My xhtml pages code is:
<h:outputText value="#{msg['elicense.examinationform.personal.classofcertificates']}"/>
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedClass}" layout="grid" columns="1">
<f:selectItems value="#{examinationFormBean.examinationPart}"var="className" itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
My bean is:
private String[] selectedClass;
private List<CertificateClass> examinationPart=new ArrayList<CertificateClass>();
getter()
setter()
The method where I want to save my checkbox is:
private void saveExaminationDetails()
{
examDetails.setElementaryPrinciples(); //bolean field
examDetails.setLightinig()
//no of setter
}
I am not able to find out how I will set the selected and not selected checkbox value on the method
Look at primefaces showcases: http://primefaces-rocks.appspot.com/ui/selectManyCheckbox.jsf
Selected values from examinationFormBean.examinationPart should setting in p:selectManyCheckbox attribute value and then you can used this selected list in bean method.
For your example should be something:
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedExaminationParts}" layout="grid" columns="1">
<f:selectItems value="#{examinationFormBean.examinationParts}" var="className" itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
And then you can use selectedExaminationParts in your saveExaminationDetails()
The p:selectManyCheckbox select values are biding a String Collection(List, ArrayList... etc) on managed bean. You just need to save each String existent on the Collection.
I will give you an example showing how you can do that:
Example:
...
#Named(value = "myBean")
#SessionScoped
public class InscricaoBean implements Serializable {
...
private List<String> selectedElemnts = new ArrayList();
//selectedElements get and set
...
On JSF you have something like:
...
<h:outputText value="#{msg['elicense.examinationform.personal.classofcertificates']}"/>
<p:selectManyCheckbox id="grid" value="#{examinationFormBean.selectedElemnts}"...>
<f:selectItems value="#{examinationFormBean.examinationPart}"var="className"
itemLabel="#{className.name}" itemValue="#{className}" />
</p:selectManyCheckbox>
...
On save method:
...
private void saveExaminationDetails()
{
for (String nameAux: selectedElemnts )
{
//you save the data here
}
}
...

<p:inputText> value not updated in model on change

I have a form that lets me edit a list of beans (one at a time), using buttons I can switch between the beans.
Keeping it simple :
public class MyBean {
private String text;
}
public class MyController {
private List<MyBean> availableBeans = new ArrayList<MyBean>(); // has five MyBeans with random text
private MyBean selectedBean; // initialized with first element of list
private int index = 0;
public void nextBean() { index++; }
public void previousBean() { index--; }
private void refreshBean() { selectedBean = availableBeans.get(index); }
}
For the html part I have something like
<h:form id="someForm">
<!-- stuff -->
<p:inputText value="#{myController.selectedBean.text}" />
<p:inplace editor="true" label="#{myController.selectedBean.text}" >
<p:inputText value="#{myController.selectedBean.text}" />
</p:inplace>
<!-- more stuff-->
</h:form>
If I change the text inside the inplace tag, the variable in myBean will be updated just fine, but If I only use inputText the bean will still have the old value, even if I change it on the webpage. Why is that?
Its because the p:inplace editor="true" implicitly submits the value to the server while <p:inputText does not do it implicitly,
You can solve it in several ways
1) add submit button like <p:commandButton to submit the value from p:inputText
2) use p:ajax event="keyup" or event="change",inside p:inputText
also take a look at the showcase p:ajax enables ajax features on supported components.
p.s , remove the value attribute from the p:inplace (there is no such attribute in p:inplace)
Lets give your components ids:
<h:form id="someForm">
<p:inputText id="first" value="#{myController.selectedBean.text}" />
<p:inplace id="second" editor="true" value="#{myController.selectedBean.text}">
<p:inputText id="third" value="#{myController.selectedBean.text}" />
</p:inplace>
</h:form>
According to the Primefaces Documentation 3.5 the component p:inplace has no attribute called value.
Do you submit the form someForm when changing the value of first? Otherwise the updated values from first won't be passed to MyController and MyBean. p:inplace submits the values automatically whereby you have to do it yourself it you use the standard p:inputText.

JSF h:selectOneMenu is never set even when using f:ajax

I want to implement a filtering facility in a JSF web application as follows: The users can add as many filters as they want. They can also delete them. So I am having a dataTable of filters. Each row consists of one h:selectOneMenu which has an ajax “change” event in order to make a second h:selectOneMenu visible in the same row. The options of the second h:selectOneMenu are calculated dynamically according to the selected option of the first.
The problem is that the value of second h:selectOneMenu is never set to the back-end object even if I added an ajax event. However the value of the first h:selectOneMenu is set.
I have the following fragment of code in an .xhtml page:
<h:form id="filterForm">
<h:dataTable id="filterTable" value="#{filterManager.filters}" var="filter">
<h:column>
<h:outputLabel value="#{msgs.filterBy}:" for="availableFilters" />
<h:selectOneMenu id="availableFilters" value="#{filter.filter}">
<f:selectItems value="#{filterManager.getProperties(typeSelector.typeSelected)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:column>
<h:column>
<h:panelGroup id="filterValuesPanel" >
<h:outputLabel value="#{msgs.value}:" for="filterValues" rendered="#{!filter.filterEmpty}" />
<h:selectOneMenu value="#{filter.value}" id="filterValues" rendered="#{!filter.filterEmpty}" >
<f:selectItems value="#{filterManager.getPossibleAnswers(filter)}" />
<f:ajax event="change" render=":filterForm" />
</h:selectOneMenu>
</h:panelGroup>
</h:column>
<h:column>
<h:commandButton value="#{msgs.delete}" title="#{msgs.deleteFilter}">
<f:ajax event="click" listener="#{filterManager.removeFilter(filter)}" render=":filterForm" />
</h:commandButton>
</h:column>
</h:dataTable>
<h:commandButton value="#{msgs.addNewFilter}">
<f:ajax event="click" listener="#{filterManager.addNewFilter}" render=":filterForm" />
</h:commandButton>
</h:form>
I have a bean called “FilterManager” which has a ViewScoped. Important parts are shown below:
#ManagedBean
#ViewScoped
public class FilterManager implements Serializable {
private List<Filter> filters; // it has a getter
private int currentFilterId;
public void addNewFilter(AjaxBehaviorEvent event) {
this.currentFilterId++;
this.filters.add(Filter.getEmptyFilter(this.currentFilterId));
}
public void removeFilter(Filter filter) {
this.filters.remove(filter);
}
...
}
The Filter class is a normal class (not a bean) and is shown below:
public class Filter implements Serializable {
private int id;
private String filter;
private String value;
public String getFilter() {
return filter;
}
public void setFilter(String theFilter) {
if (theFilter != null && !theFilter.isEmpty())
this.filter = theFilter;
}
public String getValue() {
return value;
}
public void setValue(String theValue) {
this.value = theValue;
}
public boolean isFilterEmpty() {
return this.filter == null || this.filter.isEmpty();
}
...
}
Notice that TypeSelector is a SessionScoped bean which has a typeSelected property along with getter and setter.
The problem is: filter.filter is set correctly whereas filter.value is never set. I can't find the problem so I need your help please. Apologies for all this code but I needed to provide you with all the necessary details.
Thanks in advance!
Okay guys that was my fault. I had a bug in FilterManager.getPossibleAnswers(Filter filter) method. Basically, at the end of the method, I was setting filter.value to the first element of List unconditionally. Eg instead of writing
if (filter.getValue() == null || filter.getValue().isEmpty()) {
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
}
I just wrote:
SelectItem first = answers.get(0);
filter.setValue((String) first.getValue());
Although filter.value was updating as normal, the value was changing back to default (first element in list) during re-rendering of dataTable component.

JSF update inputText after selectOneMenu choice

I want to change the inputTexts' values when I choose another Skin from my selectOneMenu.
Everything is doing well, my Converter gives back the right Object from the menu, but the inputTexts are not updated.
<h:form>
<h:selectOneMenu id="dropdownSkin"
value="#{helloBean.currentSkin}" defaultLabel="Select a skin.."
valueChangeListener="#{helloBean.skinValueChanged}" immediate="true"
onchange="this.form.submit()" converter="SkinConverter" >
<f:selectItems value="#{helloBean.mySkinsSI}" var="c"
itemValue="#{c.value}" />
</h:selectOneMenu>
<br />
<h:inputText id="name" value="#{helloBean.currentSkin.title}"></h:inputText>
<br />
<h:inputText id="tcolor" value="#{helloBean.currentSkin.titleBar.textColor}"></h:inputText>
<br />
<h:inputText id="bcolor" value="#{helloBean.currentSkin.titleBar.backgroundColorStart}"></h:inputText>
</h:form>
Here is what my Bean looks like. I debugged it and the Object currentSkin is set correctly. Now i need to know how to update the textfields content.
#ManagedBean
#SessionScoped
public class HelloBean implements Serializable {
private static final long serialVersionUID = 1L;
private List<ExtendedSkin> mySkins;
private List<SelectItem> mySkinsSI;
private ExtendedSkin currentSkin;
public void skinValueChanged(ValueChangeEvent e) {
currentSkin = (ExtendedSkin) e.getNewValue();
FacesContext.getCurrentInstance().renderResponse();
}
public List<ExtendedSkin> getMySkins() {
mySkins = XMLParser.readExtendedSkins();
return mySkins;
}
public List<SelectItem> getMySkinsSI() {
mySkinsSI = new LinkedList<SelectItem>();
for (ExtendedSkin s : getMySkins()) {
mySkinsSI.add(new SelectItem(s, s.getTitle()));
}
return mySkinsSI;
}
public void setMySkinsSI(List<SelectItem> myItems) {
this.mySkinsSI = myItems;
}
public ExtendedSkin getCurrentSkin() {
if (currentSkin == null) {
currentSkin = getMySkins().get(0);
}
return currentSkin;
}
public void setCurrentSkin(ExtendedSkin currentSkin) {
this.currentSkin = currentSkin;
}
}
The problem here is that the converter is doing its work filling the helloBean.currentSkin object, but the values in the <h:inputText> that are bounded to this helloBean.currentSkin: title, textColor and backgroundColorStart will be send to the server and replace the actual values that were loaded by the converter. In other words:
The converter is executed and builds the helloBean.currentSkin based on the selected value.
The <h:inputText id="name"> empty value is sent to server and will be injected in helloBean.currentSkin.title. Same behavior for the other 2 <h:inputText>s.
The view will be loaded using the selected helloBean.currentSkin and it will load the helloBean.currentSkin.title with the empty value. Same behavior for the other 2 <h:inputText>s.
There are two possible solutions to this problem:
Move the <h:inputText>s outside the form, so the empty values won't be send to the server. When loading the view, it will maintain the values loaded in the converter.
<h:form>
<h:selectOneMenu id="dropdownSkin"
value="#{helloBean.currentSkin}" defaultLabel="Select a skin.."
valueChangeListener="#{helloBean.skinValueChanged}" immediate="true"
onchange="this.form.submit()" converter="SkinConverter" >
<f:selectItems value="#{helloBean.mySkinsSI}" var="c"
itemValue="#{c.value}" />
</h:selectOneMenu>
</h:form>
<br />
<h:inputText id="name" value="#{helloBean.currentSkin.title}"></h:inputText>
<!-- rest of Facelets code... -->
Since you're loading the helloBean.currentSkin while changing the selected value on your dropdownlist, you can add ajax behavior using <f:ajax> tag component inside the <h:selectOneMenu> and update the fields in a cleaner way. I would opt for this solution.
<h:form>
<!-- Note that there's no need of the onchange JavaScript function -->
<h:selectOneMenu id="dropdownSkin"
value="#{helloBean.currentSkin}" defaultLabel="Select a skin.."
valueChangeListener="#{helloBean.skinValueChanged}" immediate="true"
converter="SkinConverter" >
<f:selectItems value="#{helloBean.mySkinsSI}" var="c"
itemValue="#{c.value}" />
<f:ajax process="#this" render="name tcolor bcolor" />
</h:selectOneMenu>
<br />
<h:inputText id="name" value="#{helloBean.currentSkin.title}" />
<h:inputText id="tcolor" value="#{helloBean.currentSkin.titleBar.textColor}" />
<br />
<h:inputText id="bcolor"
value="#{helloBean.currentSkin.titleBar.backgroundColorStart}" />
</h:form>
You can learn more about <f:ajax> in online tutorial like this one.
Since you're going to use an ajax call in your page, you should change your managed bean scope from #SessionScoped to #ViewScoped. More info about this here: Communication in JSF 2

Resources