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

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

我有一个非常简单的复合组件,当它被点击时,它会在两个图像之间来回切换。当我第一次点击它时,它工作正常。此后每次都没有任何反应。 "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....

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

另请参阅:

  • How to save state when extending UIComponentBase