JSF update inputText after selectOneMenu choice

jsf, selectonemenu

Solution

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

Problem

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; } } ```

Original source