I would like to have a reusable ui component which is tied to the model.
For example :
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.
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>
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.
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
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With