Strange lifecycle behaviour with f:ajax and valueChangedListener

Posted by gerry on Stack Overflow See other posts from Stack Overflow or by gerry
Published on 2010-05-21T09:38:31Z Indexed on 2010/05/21 9:40 UTC
Read the original article Hit count: 216

Filed under:
|
|
|

I want to use the f:ajax tag to update a part of a page with a editor gui, which style depends on a selectOneMenu and its selected item. The problem is, that if the ajax is called the server first renders the editor and then executes the valueChangedListener method.

In my JSF2.0 / Facelets app I've the following code:

...
<h:selectOneMenu id="typeSelect" validator="#{addEntityBean.checkType}" 
    value="#{addEntityBean.selectedTypeAsString}"
    valueChangeListener="#{addEntityBean.selectedTypeChanged}">
    <f:ajax render="editorGrid"/>
    <f:selectItems value="#{addEntityBean.entityTypeListAsString}"/>
</h:selectOneMenu>
...
<h:panelGrid id="editorGrid" columns="2" binding="#{addEntityBean.dynamicEditorGrid}" />

The BackingBean code looks like this:

public String getSelectedTypeAsString() {
        return selectedTypeAsString;
    }
    public void setSelectedTypeAsString(String selectedType) {
        this.selectedTypeAsString = selectedType;
    }
public Class<? extends Entity> getSelectedType() {
        log.severe("getSelectedType");
        Class<? extends Entity> res = null;
        if(selectedTypeAsString != null){
            int index = entityTypeListAsString.indexOf(selectedTypeAsString);
            res = entityTypeList.get(index);
        }
        return res; 
    }
    public void selectedTypeChanged(ValueChangeEvent event){
        setSelectedTypeAsString((String)event.getNewValue()); 
        Class<? extends Entity> clazz = getSelectedType();

        if(clazz != null){
            try {
                setEntity(clazz.newInstance());
            } catch (Exception e) {
                log.severe(e);
            }
        }
        else{
            setEntity(null);
        }
    }

    public HtmlPanelGrid getDynamicEditorGrid() {
        HtmlPanelGrid grid = DynamicHtmlComponentCreator.createHtmlPanelGrid();
        Entity entity = getEntity();
        if(entity != null){
            log.severe("getEntity() -->"+entity.getClassName());
            grid = (HtmlPanelGrid)buildGui(grid, entity, "entityBean.entity", false);
        }
        else log.severe("getEntity() --> null");
            return grid;
    }

The problem is, that the server logs show that at first the getDynamicEditorGrid() is executed. And later the selectedTypeChanged()-listener-method. So everytime the selected editor style type is update one selection later. I.e. after a page reload (the type is initally null) the user selects the A, now the getDynamicEditorGrid() is executed again with type null and after that the type is changed to A. Again the user selects now B (after A) and now the getDynamicEditorGrid() is executed with the type A and after that the type is changed to B.

What is wrong with my code? How can I fix this really strange behavior...

© Stack Overflow or respective owner

Related posts about jsf

Related posts about jsf2