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