如何在JSF中创建可重用的组件?

时间:2011-04-28 10:35:22

标签: java jsf jsf-2 primefaces

我希望有一个可重复使用的ui组件,它与模型绑定。

例如:

  1. 我有一个selectonemenu链接到另一个selectonemenu(如部门 - >子部门)
  2. 想将此作为复合组件
  3. 此复合组件将绑定到特定的JSF Bean
  4. 我认为如果我只使用一个compositeComponent,这个想法是有效的。

    但是如果我使用多个相同类型的复合组件,这将不起作用,因为 compositeComponent的JSF Bean将是相同的(在此示例中,我使用视图范围),以及将在一个或多个compositeComponents之间共享状态。

    这是一个粗略的例子,说明了我的困惑。在这种情况下,Page1.xhtml(使用Page1Bean.java的主模型)使用2个compositeComponents(由MyCompositeComponent.java的JSF Bean处理)

    复合组件将类似于:

    <!-- one composite component that has 2 chained selectOneMenus -->
    <h:selectOneMenu
        ...
        value="#{myCompositeComponentBean.firstComboValue}"
        valueChangeListener="#{myCompositeComponentBean.yyy}">
        <f:ajax event="valueChange" execute="@this" ... />
        <f:selectItem itemLabel="Choose one .." noSelectionOption="true" />
        <f:selectItems value="#{myCompositeComponentBean.firstComboList}" .... />
    </h:selectOneMenu>
    <h:selectOneMenu
        ...
        value="#{myCompositeComponentBean.secondComboValue}"
        valueChangeListener="#{myCompositeComponentBean.bbb}">
        <f:selectItem itemLabel="Choose one .." noSelectionOption="true" />
        <f:selectItems value="#{myCompositeComponentBean.secondComboList}" .... />
    </h:selectOneMenu>
    

    复合组件的JSF Bean就像:

    // this model will serve the composite component
    @Named
    @Scope("view")
    public class MyCompositeComponentBean {
        private String firstComboValue, secondComboValue;
        private List<String> firstComboList, secondComboList;
        ...
    }
    

    这是Page1.xhtml的一个例子:

    ....
    main department : <my:comboChainComponent /> <!-- 2 select items will be rendered here -->
    secondary department : <my:comboChainComponent /> <!-- another 2 select items will be rendered here -->
    ....
    

    Page1Bean(Page1.xhtml的主要JSF Bean)

    @Named
    @Scope("view")
    public class Page1Bean {
        // inject the first bean for the composite component 1
        @Inject private MyCompositeComponentBean bean1;
        @Inject private MyCompositeComponentBean bean2;
        ...
    }
    

    是否有可能实现这种可重用性?

    谢谢。

4 个答案:

答案 0 :(得分:4)

为什么不使用这种方法。

<mytag:combo id="combo1" 
         value="#{bean.firstData}" 
         model="#{globalBean.getList()}"
         update="form1:combo2"   />

<mytag:combo id="combo2" 
         value="#{bean.secondData}" 
         model="#{globalBean.getSubList(bean.firstData)}"  />

您可以使用复合属性。

...
<composite:interface name="combo">
   ... define your attributes here
</composite:interface>

<composite:implementation>
<p:outputPanel id="content">
    <p:selectOneMenu id="select_menu_1" value="#{cc.attrs.value}">
         <f:selectItems value="#{cc.attrs.model}" />
        <p:ajax event="change" process="@this" update="#{cc.attrs.update}" />
    //add converter if you want 
    </p:selectOneMenu>
</p:outputPanel>
</composite:implementation>

答案 1 :(得分:3)

根据您尝试实现的内容,您可以使用一些“支持组件”(=与您的facelet复合组件关联的java类)。请参阅此帖子:http://weblogs.java.net/blog/cayhorstmann/archive/2010/01/30/composite-input-components-jsf

仍然可能,根据您的实际操作,您可以更好地定义复合组件,主要是使用更多参数和更好的模型来传递值(如果需要)。我对你的应用程序缺乏一些知识,无法提供更好的建议。

答案 2 :(得分:2)

在JSF 2.0中,创建复合组件非常简单。 这是一个很好的教程: http://weblogs.java.net/blog/driscoll/archive/2008/11/writing_a_simpl.html

答案 3 :(得分:2)

我不确定我是否理解你,但您可能希望将参数传递给您构建的componentComposition。

    main department : <my:comboChainComponent worksOn="#{page1Bean.bean1}" /> <!-- 2 select items will be rendered here -->
secondary department : <my:comboChainComponent worksOn="#{page1Bean.bean2}"/> <!-- another 2 select items will be rendered here -->

希望它有所帮助...