tags:

views:

448

answers:

2

At my view I have two menus that I want to make dependent, namely, if first menu holds values "render second menu" and "don't render second menu", I want second menu to be rendered only if user selects "render second menu" option in the first menu. After second menu renders at the same page as the first one, user has to select current item from it, fill another fields and submit the form to store values in database. Both the lists of options are static, they are obtained from the database once and stay the same. My problem is I always get null as a value of the selected item from second menu. How to get a proper value? The sample code of view that holds problematic elements is:

<h:selectOneMenu id="renderSecond" value="#{Bean.renderSecondValue}"
                                 valueChangeListener="#{Bean.updateDependentMenus}"
                                 immediate="true"
                                 onchange="this.form.submit();" >
                    <f:selectItems value="#{Bean.typesOfRendering}" />
                </h:selectOneMenu><br />

<h:selectOneMenu id="iWillReturnYouZeroAnyway" value="#{Bean.currentItem}"
                                 rendered="#{Bean.rendered}" >
                    <f:selectItems value="#{Bean.items}" />
                </h:selectOneMenu><br />
<h:commandButton action="#{Bean.store}" value="#Store" />

However, if I remove "rendered" attribute from the second menu, everything works properly, except for displaying the menu for all the time that I try to prevent, so I suggest the problem is in behavior of dynamic rendering. The initial value of isRendered is false because the default item in first menu is "don't render second menu". When I change value in first menu and update isRendered with valueChangeListener, the second menu displays but it doesn't initialize currentItem while submitting.

Some code from my backing bean is below:

public void updateDependentMenus(ValueChangeEvent value) {
    String newValue = (String) value.getNewValue();
        if ("render second menu" == newValue){
            isRendered = true;
        } else {
            isRendered = false;
        }
}

public String store(){
    System.out.println(currentItem);
    return "stored";
}
A: 

The problem arises only when we have "don't render" as a first option. I decided to change the values in the database and now I have "render second menu" as a first one. With such an approach, everything works fine.

Dzmitry Zhaleznichenka
+2  A: 

If you're using the rendered attribute on UIInput and UICommand components, then you have to make sure that the rendered condition evaluates exactly the same way in the subsequent request (during submitting the form) as it was during the initial request (during displaying the form). When it evaluates false, then the request values won't be applied/validated and the model values won't be updated and no action will be invoked for the component(s) in question.

An easy fix is to put the bean in the session scope, but this has caveats as well (poor user experience when opening same page in multiple browser tabs/windows). On JSF 2.0 you could use the view scope instead. On JSF 1.x you would use Tomahawk's t:saveState for this.

BalusC
Yes, that that's what I was also thinking about. However, didn't know about the view scope. Thanks.
Dzmitry Zhaleznichenka