【问题标题】:Binding a managed bean instance to composite component将托管 bean 实例绑定到复合组件
【发布时间】:2011-09-29 23:37:48
【问题描述】:

我有一个复合组件(collapsiblePanel)。该组件使用“可折叠”bean 来提供切换功能。当我在一个页面上多次使用同一个组件时,该组件的每个实例都绑定到同一个 bean 实例。如何实现组件范围 bean 之类的东西?

collapsibleTemp.xhtml:

<cc:interface>
    <cc:attribute name="model" required="true">
        <cc:attribute name="collapsed" required="true" />
        <cc:attribute name="toggle" required="true"
            method-signature="java.lang.String f()" />
    </cc:attribute>
    <cc:actionSource name="toggle" />
    <cc:facet name="header" />
    <cc:facet name="body" />
</cc:interface>
<cc:implementation>
    <h:panelGroup layout="block" styleClass="collapsiblePanel-header">
        <h:commandButton id="toggle" action="#{cc.attrs.model.toggle}"
            styleClass="collapsiblePanel-img"
            image="#{cc.attrs.model.collapsed ? '/resources/images/plus.png' : '/resources/images/minus.png'}" />
        <cc:renderFacet name="header" />
    </h:panelGroup>
    <h:panelGroup layout="block" rendered="#{!cc.attrs.model.collapsed}">
        <cc:insertChildren />
        <cc:renderFacet name="body"></cc:renderFacet>
    </h:panelGroup>
    <h:outputStylesheet library="css" name="components.css" />
</cc:implementation>

支持 bean:

@ManagedBean
@ViewScoped
public class Collapsible {

    private boolean collapsed = false;

    public boolean isCollapsed() {
        return collapsed;
    }

    public void setCollapsed(boolean collapsed) {
        this.collapsed = collapsed;
    }

    public String toggle() {
        collapsed = !collapsed;
        return null;
    }

}

使用页面

<h:form id="someid">
    <jl:collapsibletemp id="collapsiblePanel1" model="#{collapsible}">
        <f:facet name="header">
            <h3>
                <h:outputText value="Collapsible information" />
            </h3>
        </f:facet>
        <f:facet name="body">
            <h:outputText value="do something....." />
        </f:facet>
        <p />
    </jl:collapsibletemp>

    <jl:collapsibletemp id="collapsiblePanel2" model="#{collapsible}">
        <f:facet name="header">
            <h3>
                <h:outputText value="Collapsible information" />
            </h3>
        </f:facet>
        <f:facet name="body">
            <h:outputText value="do some tabbing" />
        </f:facet>
        <p />
    </jl:collapsibletemp>

    <jl:collapsibletemp id="collapsiblePanel3" model="#{collapsible}">
        <f:facet name="header">
            <h3>
                <h:outputText value="Collapsible information" />
            </h3>
        </f:facet>
        <f:facet name="body">
            <h:outputText value="notice board" />
        </f:facet>
        <p />
    </jl:collapsibletemp>
</h:form>

【问题讨论】:

    标签: jsf-2 composite-component managed-bean


    【解决方案1】:

    您可以使用&lt;cc:interface&gt;componentType 属性来定义“支持组件”。

    例如

    <cc:interface componentType="collapsiblePanel">
        ...
    </cc:interface>
    <cc:implementation>
        ...
        <h:commandButton action="#{cc.toggle}" ... />
        ...
        <h:panelGroup rendered="#{!cc.collapsed}" ...>
        ...
    </cc:implementation>
    

    只有com.example.components.CollapsiblePanel

    @FacesComponent(value="collapsiblePanel") // To be specified in componentType attribute.
    public class CollapsiblePanel extends UINamingContainer { // Important! Must extend UINamingContainer.
    
        private boolean collapsed;
    
        public void toggle() {
            collapsed = !collapsed;
        }
    
        public boolean isCollapsed() {
            collapsed;
        }
    
    }
    

    然而,当您想要拥有多个这些组件时,您应该在视图中声明它们的物理上分离实例。如果这需要动态发生,那么您需要使用&lt;c:forEach&gt; 来生成物理上独立的实例,而不是使用单个组件的&lt;ui:repeat&gt;。否则,您必须通过 Map&lt;String, Boolean&gt; 中的客户端 ID 映射所有 collapsed 状态。有关示例和更多背景信息,请参见 Getting same instance of `componentType` in composite component on every use

    【讨论】:

    • 此解决方案部分有效。当我切换一个组件时,另一个组件也会被切换。我已经手动声明了 3 次组件。当我切换任何一个组件时,其他 2 个组件也会切换。 谢谢你的帮助。请让我知道我可以做些什么来使这些组件彼此完全独立。
    • 这正是我在回答的最后一段中已经预测和涵盖的内容。使用 &lt;c:forEach&gt; 或将布尔值保存在以客户端 ID 作为键的映射中。
    • 我按照您的建议进行了更改。但它似乎仍然不起作用。使用页面: @ManagedBean(name ="widgets") public class Widgets { public List getWindows() { if(windows == null){ windows = new ArrayList(); windows.add(new Window("one", "one header", "one body")); windows.add(new Window("two", "two header", "two body")); } 返回窗口;即使将折叠状态添加到地图中,它们的行为也不像独立组件。
    • @FacesComponent(value = "collPanelTwo") class CollPanel extends UICompBase implements NContainer { public void toggle(ActionEvent evt) { collapsed = !collapsed; testMap.put(getClientId(), isCollapsed()); } public boolean isCollapsed() { return testMap.get(getClientId()); } USING PAGE facets... facets... 我在视图中手动添加了 2 个组件.它们的行为不像独立的组件。我也尝试过
    • 感谢 BalucS。我不得不解决一些问题才能让它工作。我使用 stateHelper 来保存状态。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-30
    • 2015-05-06
    • 2012-06-03
    • 2012-11-08
    • 2011-10-29
    • 2016-07-09
    相关资源
    最近更新 更多