bobzer
bobzer

Reputation: 163

primefaces dont validate ajax rendered component

<h:form id="formEdit">
    <p:selectOneMenu value="#{testView.selection}"
                     required="true">
        <f:selectItem itemValue="noMenu" itemLabel="selectOneMenu not rendered"/>
        <f:selectItem itemValue="haveMenu" itemLabel="selectOneMenu rendered"/>
        <p:ajax update="formEdit"/>
    </p:selectOneMenu>
    <p:panel>
        <p:selectOneMenu id="conditionallyRnedered" value="#{testView.value}"
                         rendered="#{testView.selection eq 'haveMenu'}"
                         required="true">
            <f:selectItem itemValue="#{null}" itemLabel="-" noSelectionOption="true"/>
        </p:selectOneMenu>
    </p:panel>
    <p:messages id="messages"/>
    <p:commandButton value="Submit"/>
</h:form>

Component "conditionallyRnedered" is required, and rendered on page after i select "haveMenu" value in first menu. This component have only empty option and initialy its not rendered on page. If i press Submit button, then response is:

<partial-response><changes>
<update id="javax.faces.ViewState"><![CDATA[stateless]]></update>
</changes></partial-response>

There is no validation error. If i change value of rendered attribute in "conditionallyRnedered" from "#{testView.selection eq 'haveMenu'}" to just "true", then response is:

<partial-response><changes>
<update id="javax.faces.ViewState"><![CDATA[stateless]]></update>
<extension ln="primefaces" type="args">{"validationFailed":true}</extension></changes>
</partial-response>

Validation error returned. The questions is:

  1. Why conditionally rendered component is not validated?
  2. It is possible to make them validated?

UPD Originally in my question is absent Bean source code, in which Bean declared as @ViewScoped. After read @BalusC comment, i try to change scope from @ViewScoped to @SessionScoped, and after that validation is working correctly. Wherein javax.faces.ViewState in response changed from stateless to some view id:

<update id="javax.faces.ViewState">-5902669082498843838:729675320168079573</update>

I still doubt, this is solution or still workaround, because I thought that instance of @ViewScoped bean is exist while we dont left the page. Maybe this behavior is caused by the fact that in the same page present another bean, with @SessionScoped scope.

Upvotes: 2

Views: 1724

Answers (2)

BalusC
BalusC

Reputation: 1108722

It failed for the technical reason explained in this Q&A: Form submit in conditionally rendered component is not processed. In a nutshell, JSF will re-check the rendered attribute during processing the form submit/conversion/validation and skip components which aren't rendered during that moment. The answer is to use a @ViewScoped bean.

That it still failed in spite of that you're actually using a @ViewScoped bean is because you're using a stateless view via <f:view transient="true">, as confirmed by the actual javax.faces.ViewState value and What is the usefulness of statelessness in JSF? In other words, JSF won't save/restore the view, including any view scoped beans. Those beans will technically behave like @RequestScoped beans and thus be recreated on every request, resetting their properties to defaults everytime.

To solve your problem, just turn off stateless view by removing <f:view transient="true"> and keep your bean @ViewScoped.

Upvotes: 3

Mahendran Kandiar
Mahendran Kandiar

Reputation: 980

@bobzer,

primefaces commandButton has become ajax="true" by default. So when i set ajax="false", the form is submitted and i can see validation errors

i get validation error coming

My xhtml:

    <h:form id="formEdit">
    <p:selectOneMenu value="#{testView.selection}" required="true">
        <f:selectItem itemValue="noMenu"
            itemLabel="selectOneMenu not rendered" />
        <f:selectItem itemValue="haveMenu" itemLabel="selectOneMenu rendered" />
        <p:ajax update="formEdit" />
    </p:selectOneMenu>
    <p:panel>
        <p:selectOneMenu id="conditionallyRnedered" value="#{testView.value}"
            rendered="#{testView.selection eq 'haveMenu'}" required="true">
            <f:selectItem itemValue="#{null}" itemLabel="-"
                noSelectionOption="true" />
        </p:selectOneMenu>
    </p:panel>
    <p:messages id="messages" />
    <p:commandButton value="Submit" ajax="false"/>
</h:form>

My Bean

        package citi.manageID.framework.admin.roleMgmt;

    import javax.faces.view.ViewScoped;
    import javax.inject.Named;

    @Named
    @ViewScoped
    public class TestView {


        private String selection="";

        private String value="";

        public String getSelection() {
            return selection;
        }

        public void setSelection(String selection) {
            this.selection = selection;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }


    }

Upvotes: -1

Related Questions