Is there a way to prevent JSF from displaying previous/outdated content in h:selectManyMenu after validation error?

StackOverflow https://stackoverflow.com/questions/18783634

Domanda

I have a form with, say a text field and a multi-select field.

<h:form id="form2">
    <h:messages for="text3" />
    <h:inputText id="text3" value="#{danielBean.text3}" required="true"/>
    <br/>

    <h:messages for="select1" />
    <h:selectManyMenu id="select1" value="#{danielBean.selStrings}"
        style="height:8em;" required="true"/>
        <f:selectItems value="#{danielBean.allStrings}" var="_item" itemLabel="#{_item} (length #{_item.length()})" />
    <br/>
    <p:commandButton
        value="Submit"
        action="#{danielBean.save()}"
        update=":form2"
    >
</h:form>

On submit, both get validated, and if validation is successful, the relevant variables in the backing bean are updated. Fair enough.

The problem happens when the validation (of the multi-select) is NOT successful. In my Bean, I have (particularly for the List<String>s allStrings and selStrings)...

@PostConstruct
public void init() {
    text3 = "";

    allStrings.clear();
    allStrings.add("This");
    allStrings.add("is");
    allStrings.add("a");
    allStrings.add("test");

    selStrings.clear();
    selStrings.add("a");
}

...so that the multi-select has one pre-selected option. If the user unselects that option (i.e. no options chosen), the validation will -of course- fail, an error message will be displayed...

...but the multiselect will not be empty. It will show the content from the bean, i.e. "a" selected. This is confusing to the user - getting an error message "input required", and being shown a filled-out field.

This appears to be a feature of JSF's lifecycle, see this article by BalusC:

"When JSF renders input components, then it will first test if the submitted value is not null and then display it, else if the local value is not null and then display it, else it will display the model value."

This works fine for the text field text3, because it submits as an empty string, not null.

The problem is that zero selected options from a multi-select means that the submitted value is null, that the local copy (I guess, since it's the first submit) is null, so that the model value ("a" selected) is displayed.

I do not want that.

How can I force JSF to use the null value it got submitted when rendering the validation response?

Thanks in advance
Antares42

È stato utile?

Soluzione

There is no solution for this (other than reporting an issue to JSF guys and/or hacking in JSF source code). There's however a workaround: update only the components which really need to be updated on submit. Currently, you've set ajax to update the entire form. How about updating just the messages?

<h:messages id="text3_m" for="text3" />
...
<h:messages id="select1_m" for="select1" />
...
<p:commandButton ... update="text3_m select1_m" />

You can if necessary make use of PrimeFaces Selectors to minimize the boilerplate if you have rather a lot of fields:

<h:messages for="text3" styleClass="messages" />
...
<h:messages for="select1" styleClass="messages" />
...
<p:commandButton ... update="@(.messages)" />
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top