Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make reusable component in JSF?

I would like to have a reusable ui component which is tied to the model.

For example :

  1. I have a selectonemenu that is chained to another selectonemenu (like department -> sub-department)
  2. Would like to make this a composite component
  3. This composite component is going to be tied to a specific JSF Bean

I think this idea works if im only using one compositeComponent.

But this will not work if i make use of more than one compositeComponent of the same type, since the compositeComponent's JSF Bean will be the same (in this example, im using view scope), and will share the state between one or more compositeComponents.

This is one rough example that illustrates my confusion. In this case, Page1.xhtml (with the main model of Page1Bean.java), makes use of 2 compositeComponents (which is handled by the JSF Bean of MyCompositeComponent.java)

The composite component will be something like :

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

And the composite component's JSF Bean will be like :

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

This is an example of 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 -->
....

And the Page1Bean (Main JSF Bean for Page1.xhtml)

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

Is it possible to achieve this kind of reusability?

Thank you.

like image 831
Albert Gan Avatar asked Apr 28 '11 10:04

Albert Gan


4 Answers

Why don't use this kind of approach.

<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)}"  />

You can use composite attribute.

...
<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>
like image 170
Ali Irawan Avatar answered Nov 18 '22 16:11

Ali Irawan


Depending on what you are trying to implement, you could use some "backing component" (=a java class associated to your facelet composite component). See this post: http://weblogs.java.net/blog/cayhorstmann/archive/2010/01/30/composite-input-components-jsf

Still maybe, depending on what your are really doing, you could probably better define your composite components, mainly using more parameters and a better model for passing values (if needed). I'm lacking some knowledge of your app to give a better advice.

like image 24
ymajoros Avatar answered Nov 18 '22 16:11

ymajoros


In JSF 2.0, creating composite components is a snap. Here is a good tutorial: http://weblogs.java.net/blog/driscoll/archive/2008/11/writing_a_simpl.html

like image 2
Mehrez Marouani Avatar answered Nov 18 '22 15:11

Mehrez Marouani


Not sure I understand you perfectly, but you might want to pass an argument to the componentComposition you build.

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

Hope it helps...

like image 2
alfonx Avatar answered Nov 18 '22 15:11

alfonx