进一步了解jsf 2视图范围的理解过程,我再次遇到问题。
创建了我的复合组件绑定对象的多个实例,并且设置值似乎不是针对“正确”的。
我的初始设置与Auto-instantiate session-scoped bean from view-scoped bean
相同现在我创建了一个复合组件:
<composite:interface componentType="helloWidget">
</composite:interface>
<composite:implementation>
<h:outputText value="Visible state of this composite component: #{cc.visibleState}"/>
</composite:implementation>
及其java对应
@FacesComponent(value = "helloWidget")
public class HelloWidget extends UINamingContainer implements Serializable {
private static final long serialVersionUID = 2L;
private boolean visible;
public void show() {
System.out.println("Setting visible state to true " + this);
visible = true;
}
public void hide() {
System.out.println("Setting visible state to false " + this);
visible = false;
}
public String getVisibleState() {
System.out.println("Getting visible state of " + this + "(" + visible + ")");
return String.valueOf(visible);
}
}
然后我升级了我的ViewBean.java
private HelloWidget helloWidget;
private boolean visible;
public String getVisibleState() {
return String.valueOf(visible);
}
public void actionShow(ActionEvent ae) {
visible = true;
helloWidget.show();
}
public void actionHide(ActionEvent ae) {
visible = false;
helloWidget.hide();
}
public HelloWidget getHelloWidget() {
return helloWidget;
}
public void setHelloWidget(HelloWidget helloWidget) {
this.helloWidget = helloWidget;
}
和我的hello.xhtml:
<f:view>
<h:form>
<h:outputText value="View-scoped bean visible value: #{viewBean.visibleState}"/>
<br/>
<mycc:helloWidget binding="#{viewBean.helloWidget}"/>
<br/>
<h:commandButton value="Show" actionListener="#{viewBean.actionShow}"/>
<h:commandButton value="Hide" actionListener="#{viewBean.actionHide}"/>
</h:form>
</f:view>
当我现在点击show / hide按钮时,视图范围bean中“visible”属性的值会按预期更改。 HelloWidget属性的“可见”值也会更改,但是当显示页面时,会显示一个不同的HelloWidget实例,其可见设置为(默认)false。
我在这里做错了什么?我绑定复合组件的方式有问题吗?
答案 0 :(得分:1)
在构建/恢复视图期间实例化组件。因此它们基本上是请求作用域。您希望在视图范围中保留的任何状态都需要存储在JSF视图状态中。通常的做法是让表示视图作用域状态的属性的getter / setter委托给UIComponent#getStateHelper()
。
所以,这应该做:
@FacesComponent(value = "helloWidget")
public class HelloWidget extends UINamingContainer implements Serializable {
private static final long serialVersionUID = 2L;
public void show() {
setVisible(true);
}
public void hide() {
setVisible(false);
}
public Boolean getVisible() {
return (Boolean) getStateHelper().eval("visible");
}
public void setVisible(Boolean visible) {
getStateHelper().put("visible", visible);
}
}
然而,您有另一个与此问题无关的潜在问题:在视图范围的bean属性上使用binding
会导致在每个请求期间重新创建视图范围bean本身。谨慎使用binding
attribtue。这个问题与JSTL in JSF2 Facelets... makes sense?中已经解释过的理由相同。