Composite component action attribute reutilization? - jsf-2

I have a JSF 2.0 composite component as follows:
<composite:interface>
<composite:attribute name="id"/>
<composite:attribute name="action1" targets="#{cc.clientId}:#{cc.attrs.id}_1" requiered="true"/>
<composite:attribute name="action2" targets="#{cc.clientId}:#{cc.attrs.id}_2" requiered="true"/>
</composite:interface>
<composite:implementation>
<h:commandLink id="#{cc.attrs.id}_1" value="command link 1"/>
<h:commandLink id="#{cc.attrs.id}_2" value="command link 2"/>
</composite:implementation>
as you can see for now I am using two different attributes named (action1, action2) and target them to the two commandLink's.
what I would like to do is: instead of having action1 & action2, I would like to have only one attribute named "action" and reuse this action for both commandLinks.
Thanks.

You can specify a space separated list of client IDs in targets attribute. See also the <composite:attribute> tag documentation:
If this element has a method-signature attribute, the value of the targets attribute must be interpreted as a space (not tab) separated list of client ids (relative to the top level component) of components within the <composite:implementation> section.

Related

How to hide components by selecting a new value on h:selectOneMenu?

I have a page with a h:selectOneMenu, and I want to hide a dataTable when I choose a new value on the h:selectOneMenu while some bean attribute values update. I'm trying diferent things, and I'm able to hide the dataTable by reloading the page. I have tried this using some JavaScript code, on onsomething attributes. In that case, those bean attribute values disapear although I use t:saveState (and I also need the view scope for the bean).
Here is a little example to clarify this:
<h:selectOneMenu id="list" value="#{Bean.id}">
<f:selectItems value="#{Bean.List}" var="element" itemLabel="#{element.name}" itemValue="#{element.id}"/>
<t:saveState value="#{Bean.id}"/>
<f:ajax listener="#{Bean.populateBean}" render=":form:period" event="change"/>
</h:selectOneMenu>
<h:selectOneMenu id="period" value="#{Bean.period}">
<f:selectItems value="#{Bean.listaPeriod}" var="period" itemLabel="#{period[1]}" itemValue="#{period[0]}"/>
<t:saveState value="#{Bean.period}"/>
</h:selectOneMenu>
<h:commandButton id="search" action="#{Bean.doSearch}"></h:commandButton>
<t:dataTable id="data" value="#{Bean.configList}" rendered="#{Bean.search}"
<t:column>
...
</t:dataTable>
And Bean.doSearch changes Bean.search to true. How can I hide the dataTable when I choose a new value on h:selectOneMenu id="list"?
EDIT:
In short, the search button renders the table, and I would want to hide that table when I just choose a new value on the "list" dropdown without reloading the page. Now, the <f:ajax> is used only to rerender the "period" dropdown value.
Thanks in advance!
Your question is hardly understandable, but if you want to kick the datatable out of your view on ajax request triggered by your dropdown, you need to enclose it in a component that's always present in the view so that HSF would know what to rerender when ajax call successfully finishes:
<h:panelGroup id="rerender">
<t:dataTable rendered="#{bean.condition}" ...>
....
</t:dataTable>
<h:panelGroup>
Of course, to get it working you should specify id of the component to be rerendered:
<h:selectOneMenu ...>
...
<f:ajax listener="#{bean.populate}" render="rerender" />
</h:selectOneMenu>
Note that if both dropdown and datatable components belong to the same form, it's not necessary to specify absolute id of the latter's parent. Also note that specifying event is redundant, as it already defaults to the right one. Finally, as you're on JSF 2.x, using save state is not necessary, just bind the values of your form data to a view scoped bean.
The last thing to note is the fact that you fail to conform to the Java Naming Conventions, the thing you should correct as soon as possible.

Create composite component for f:metadata

I want to create a composite component which adds some common meta data to views, like:
<viewController:metadata controller="orderController"/>
the component:
<composite:interface>
<composite:attribute name="controller" />
</composite:interface>
<composite:implementation>
<f:metadata>
<f:viewParam name="id" value="#{cc.attrs.controller.id}" />
<f:event type="preRenderView"
listener="#{cc.attrs.controller.initConversation}" />
</f:metadata>
</composite:implementation>
i do similar things to add a button bar to all views and it works fine, but it seems its not possible with f:metadata.
Am i right or is there something wrong with my code?
thanks
This isn't possible. The <f:metadata> has to go in the view associated with the view ID. See also the tag documentation (emphasis mine):
Declare the metadata facet for this view. This must be a child of the <f:view>. This tag must reside within the top level XHTML file for the given viewId, or in a template client, but not in a template. The implementation must insure that the direct child of the facet is a UIPanel, even if there is only one child of the facet. The implementation must set the id of the UIPanel to be the value of the UIViewRoot.METADATA_FACET_NAME symbolic constant.

How to edit data in Primefaces DataTable without in-cell editing?

I have 2 pages.
Add Page for add a new item
List Page for show all items
When I click on Edit icon on List Page, I want to show selected data on Add Page for editing and update its data if I click on save button. How to do this?
Pass the row identifier as a parameter to the button. For example, assuming that #{item} is the currently iterated item and has some Long id property which uniquely identifies the item.
<p:button icon="ui-icon-pencil" outcome="edit.xhtml">
<f:param name="id" value="#{item.id}" />
</p:button>
In the target page, edit.xhtml, you can use <f:viewParam> to convert, validate and set it as a bean property.
<f:metadata>
<f:viewParam name="id" value="#{bean.item}" required="true" converter="itemConverter" />
</f:metadata>
...
<p:inputText value="#{bean.item.name}" />
<p:inputText value="#{bean.item.shortName}" />
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
Communication in JSF 2.0 - Processing GET request parameters

How to navigate with request parameters?

I want to navigate from one page to another page, say from page1 with bean1 to page2 with bean2. I need to pass some parameters from bean1 to bean2.
I would like to understand how to use #ManagedProperty for parameters and <f:viewParam> in <f:metadata> portion of page2. Say, I have field1, field2 and field3 available in bean1 and bean2 with getters and setters. My understanding is that I will have to define view params in Metadata of page2:
Like
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}"/>
<f:viewParam name="field2" value="#{bean2.field2}"/>
<f:viewParam name="field3" value="#{bean2.field3}"/>
</f:metadata>
I am not sure where I use annotations for #ManagedProperty to define the parameters field1, field2 and field3, in bean1 or bean2.
On page1 I can use "page2?faces-redirect=true&includeViewParams=true"
Can I use the same in one of my methods instead in page1, say on response to a submit of commandlink?
If I need to have those three fields in both page1 and page2, can I define those hidden fields?
You need to specify them as <f:param> in the <h:link> of page1.xhtml.
<h:link value="Go to page2" outcome="page2">
<f:param name="field1" value="#{bean1.field1}" />
<f:param name="field2" value="#{bean1.field2}" />
<f:param name="field3" value="#{bean1.field3}" />
</h:link>
You can then use <f:viewParam> (or #ManagedProperty, but this allows less fine grained validation) to set them in bean of page2.xhtml.
<f:metadata>
<f:viewParam name="field1" value="#{bean2.field1}" />
<f:viewParam name="field2" value="#{bean2.field2}" />
<f:viewParam name="field3" value="#{bean2.field3}" />
</f:metadata>
You do not need to send a POST request by <h:commandLink> with faces-redirect and includeViewParam here. Just a simple GET request by <h:link> is much simpler and SEO friendlier.
See also:
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
ViewParam vs #ManagedProperty(value = "#{param.id}")
When should I use h:outputLink instead of h:commandLink?
Communication in JSF 2.0 - Processing GET request parameters

Why does composite component "rendered" attribute throw an IllegalArgument Exception?

I create a composite component like this:
<cc:interface>
<cc:attribute name="value"
required="true" />
<cc:attribute name="rendered"
displayName="True to render"
default="true" />
</cc:interface>
When I invoke this component, I get an IllegalArgumentException. I can changed the rendered name to something else (like doIt) and then it works.
Is the rendered attribute reserved somehow? I want my composite component to look like "regular" JSF components.
This is with Mojarra.
Composite components extend UINamingContainer which in turn extend UIComponentBase which in turn already definies the id and rendered attributes. You don't need to specify them yourself. Just remove the <cc:attribute name="rendered">. If you specify the rendered attribute on the composite component tag, then it'll be interpreted and applied on the composite component itself.
If you intend to render specific children of the composite, then better invent a different attribute name. For example, renderSomeChild.

Resources