将托管 Bean 实例绑定到复合组件

发布于 2024-11-18 16:42:55 字数 3098 浏览 7 评论 0原文

我有一个复合组件(collapsiblePanel)。该组件使用“collapsible”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>

I have a composite component (collapsiblePanel). The component uses the "collapsible" bean to provide the toggle function. When I use the same component multiple times on a page, each instance of the component is bound to the same bean instance. How Can I achieve something like a component scoped 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>

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

}

Using Page

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

删除→记忆 2024-11-25 16:42:55

您可以使用 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;
    }

}

但是,当您想要拥有多个这些组件时,那么您应该声明物理上独立视图中它们的实例。如果这需要动态发生,那么您需要使用 生成它们的物理上独立的实例,而不是使用单个 成分。否则,您必须通过 Map 内的客户端 ID 映射所有 collapsed 状态。另请参阅示例和更多背景信息获取每次使用复合组件时都会使用相同的“componentType”实例

You can use the componentType attribute of the <cc:interface> to define a "backing component".

E.g.

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

with just a 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;
    }

}

However, when you want to have multiple of those components, then you should declare physically separate instances of them in the view. If this needs to happen dynamically, then you need to use <c:forEach> to generate physically separate instances of them instead of <ui:repeat> with a single component. Otherwise you have to map all collapsed states by the client ID inside a Map<String, Boolean>. See for an example and more background information also Getting same instance of `componentType` in composite component on every use

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文