Ajax call to toggle a composite component boolean variable seems to work only once

戏子无情 提交于 2019-12-24 11:31:57

问题


I have a pretty simple composite component which toggles back and forth between two images when it is clicked. When I click it the first time, it works fine. Every time after that, nothing happens. The "toggleSingleSelect" is called, but the panel itself is not re-rendered.

singleMultiSelectText.xhtml:

<cc:interface componentType="singleMultiSelect">

</cc:interface>

<cc:implementation>

    <h:panelGroup id="singleMultiSelectPanel" styleClass="field" layout="block">

        <h:commandButton styleClass="toggle" 
                         image="#{cc.singleSelect ? 
                                  '/resources/img/expand-single.gif' : 
                                  '/resources/img/collapse-single.gif'}">
            <f:ajax listener="#{cc.toggleSingleSelect}"
                    execute="@this" render="singleMultiSelectPanel"/>
        </h:commandButton>

    </h:panelGroup>

</cc:implementation>

singleMultiSelect.java:

@FacesComponent(value = "singleMultiSelect")
public class SingleMultiSelect extends UINamingContainer {

private boolean singleSelect = true;

public void toggleSingleSelect(AjaxBehaviorEvent event) {
    singleSelect = ! singleSelect;
}    

}

The console has the following output when I click it the first time:

update["assetSearchForm:j_idt112:_t113"]: <input class="toggle" id="assetSearchFor....
update["javax.faces.ViewState"]: -4115183671224810146:2892643767875659913....

Every time after that, though, I just get:

update["javax.faces.ViewState"]: -4115183671224810146:2892643767875659913....

回答1:


JSF components are created during view build time of every request. In other words, JSF component instances are basically request scoped.

Your singleSelect property needs to be retained across postbacks on the same view. In other words, you want it to be view scoped.

However, you assigned it as an instance variable of the component instead of explicitly saving it in the JSF view state. So, during every request, it would reinitialize back to its default value of true, and effectively become false every time you press the button.

You need to explicitly save view scoped state in the JSF view state. You can use the inherited getStateHelper() method for this.

public void toggleSingleSelect(AjaxBehaviorEvent event) {
    setSingleSelect(!isSingleSelect());
}

public void setSingleSelect(boolean singleSelect) {
    getStateHelper().put("singleSelect", singleSelect);
}

public boolean isSingleSelect() {
    return (boolean) getStateHelper().eval("singleSelect", true);
}

See also:

  • How to save state when extending UIComponentBase


来源:https://stackoverflow.com/questions/30435015/ajax-call-to-toggle-a-composite-component-boolean-variable-seems-to-work-only-on

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!