Ajax调用切换复合组件布尔变量似乎只工作一次

时间:2015-05-25 09:22:44

标签: ajax jsf render composite-component

我有一个非常简单的复合组件,当它被点击时,它会在两个图像之间来回切换。当我第一次点击它时,它工作正常。之后每次都没有任何反应。调用“toggleSingleSelect”,但不重新渲染面板本身。

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;
}    

}

第一次点击时,控制台有以下输出:

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

每次之后,我都会得到:

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

1 个答案:

答案 0 :(得分:2)

在每个请求的视图构建期间创建JSF组件。换句话说,JSF组件实例基本上是请求范围的。

您的singleSelect属性需要在同一视图的回发中保留。换句话说,您希望它是视图范围。

但是,您将其指定为组件的实例变量,而不是将其明确保存在JSF视图状态中。因此,在每次请求期间,它会重新初始化为默认值true,并且每次按下按钮都会有效地变为false

您需要在JSF视图状态中显式保存视图范围状态。您可以使用继承的getStateHelper()方法。

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);
}

另见: