1
<h:form>
 <h:selectManyMenu id="carsList"
                   value="#{bean.carList}"
                   style="width:400px; height:100px" label="List">
                    <f:selectItems  value="#{bean.cars}" var="i"
                                    itemLabel="#{i.code}" itemValue="#{i.Name}" />
                    <f:selectItem  itemLabel="Other" itemValue="other"/>
                    <f:ajax event="change" execute="@this" render="othermodel"/>
        </h:selectManyMenu>
                    <br></br>
                    <h:panelGroup id="othermodel">
                            <h:outputText  value="Others:" style="margin-top:10px;color:red;font-weight:bold;"
                            rendered="#{bean.carList.contains('other')}" />
                            <h:inputText size="50" id="otherinput" required="true"
                            rendered="#{bean.carList.contains('other')}"/>
                            <h:message for="otherinput"></h:message>
                    </h:panelGroup>
                       <h:commandButton value="Next" action="#{bean.submitForm}"/>
    </h:form>

My bean is requestScoped and when my carList has a value other i am able to show the panelGrid but when user don't enter any value in the input field rendered using AJAX , even i specificed required=true but it's not getting validated. And value of the input text box is null in the backend code.

How can I do the validation for the input field rendered using AJAX and why my value is coming as null? I am using JSF 2.0

SRy
  • 2,901
  • 8
  • 36
  • 57

2 Answers2

1

The rendered attribute is re-evaluated during the request of the form submit. Your bean is request scoped and thus recreated on every single request (also ajax requests) with all properties set to default. So the carList property will also be emptied and the rendered attribute would evalute false before the update model values phase has filled the carList. So, for JSF, the <h:inputText> is never rendered and thus it won't be processed.

Put the bean in the view scope instead. It'll live as long as you interact with the same view by (ajax) postbacks. It's the right scope for dynamic ajax based forms with a lot of conditional rendering.

See also:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • @BalusC.....Hey after i made bean as viewscoped and made my `service` class which is used to do database call is injected with `@Managedproperty` but it's never been intialized...I made it transient.It's an interface.How to initialize that service. – SRy Feb 06 '13 at 02:55
  • A service class should not be a JSF managed bean at all (they are not used directly in the view nor are they able to properly manage DB transactions), but an EJB (e.g. `@Stateless`). They are injected as serializable proxies, so you don't need to make them transient. – BalusC Feb 06 '13 at 02:58
  • Yeah my service class is Spring Managed bean. If I don't use `transient` it's throwing `Notserializable`Exception. – SRy Feb 06 '13 at 03:15
  • Ah well. Bad luck. It's indeed not the first time I see someone having this kind of problem with Spring managed beans. Well, I can't help you much with that other than recommending to just use the standard Java EE stack. EJBs are much more slick (no XML mess necessary) and by default already serializable. – BalusC Feb 06 '13 at 03:17
  • Unfortunately I can't change the configuration now.Cause we are moving to production in couple of days.Is `viewScoped`only solution my above issue or is there any other I can achieve this. – SRy Feb 06 '13 at 03:19
  • Maintain the state using request parameters and `@ManagedProperty`/`@PostConstruct`. You only need to convert/validate them yourself. You're basically repeating the job which JSF is supposed to transparently do for you. – BalusC Feb 06 '13 at 03:27
  • Can you give some example of that?I don't have any idea how to do that? – SRy Feb 06 '13 at 03:46
  • In this particular example, get the submitted value of `` as `String[]` yourself via `@ManagedProperty("#{paramValues['formId:carsList']}")` and manipulate if necessary the `carList` property based on that in the `@PostConstruct`. – BalusC Feb 06 '13 at 11:08
  • @BalusC...... I tried the above approach with `@ManagedProperty("#{paramValues['formId:carsList']}") ` with request scoped bean but not able to get the value of the input text when `commandButton` clicked and form is being submitted. it's null in the `@postconsturct` of the bean.Is there any way I can get the value of the input text entered by user when form is submitted?But i see that value when my control goes out of the `postconstruct.` – SRy Feb 06 '13 at 20:04
  • Have you changed your `` to have `id="formId"`? Do you in any way *understand* how JSF generates input field names (which becomes HTTP request parameters) and how the webbrowser submits the form and what that EL expression does? Look at the JSF-generated HTML output. Look at the webbrowser's builtin HTTP traffic monitor. Look at the HTTP request parameter map during form submit. – BalusC Feb 06 '13 at 20:05
  • Yes i have a `formId` this is how I mentioned in my bean `@ManagedProperty("#{paramValues['myForm:carsList']}") private String[] comboVal;`. I am able to get the values from combo box but not the input text value within the `postconstructor` – SRy Feb 06 '13 at 20:32
  • Just add another `@ManagedProperty` for it. Model values are not available in `@PostConstruct`. They are set by JSF during update model values phase which is long after bean's construction. That's exactly why you need `@ManagedProperty` and `@PostConstruct`. – BalusC Feb 06 '13 at 20:33
  • @BalusC.......Thank you very much. It's finally working with request scoped bean...... – SRy Feb 07 '13 at 01:34
  • @BalusC......simple solution to my issue is adding `p:messages` at the start of the form tag.It's rendering properly as I expected in request scoped bean without doing anything. – SRy Feb 07 '13 at 07:31
0

I tried this with @ViewScope. When I made my Spring managed service as transient I was getting null reference after deserialization. So, i tried the below method to get the Spring Service.

    @ManagedBean(name="bean")
    @ViewScoped
    public class Bean implements Serializable {


    @ManagedProperty(value="#{appService}")
    private transient AppService appService;

      // Getting AppService Object which is singleton in the application during deserialization 
     private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException {
              stream.defaultReadObject();
              FacesContext context = FacesContext.getCurrentInstance();
              appService = (AppService)context.getApplication()
                    .evaluateExpressionGet(context, "#{appService}", AppService.class);
                  stream.close();  // not sure i have to do this
           }
    }

This is working for me without any issues.

SRy
  • 2,901
  • 8
  • 36
  • 57