Create composite component for f:metadata - jsf-2

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.

Related

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

Composite component action attribute reutilization?

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.

JSF method of f:event preRenderView called after c:forEach

I'm doing a page with jsf 2.0 and i wanna do something like this:
<f:metadata>
<f:viewParam name="id" value="${id}" />
<f:event type="preRenderView" listener="#{controller.initPage(id)}"/>
</f:metadata>
....(Some code)....
<c:forEach items="#{bean.listLoadedByInitPage}" var="var">
#{var.something}
</c:forEach>
The method initPage(id) must load list in the bean. But seems that method is called after than c:forEach loads items not before. Any ideas?
JSTL tags runs during view build time. The <f:event type="preRenderView"> runs right before view render time. In other words, <c:forEach> runs before <f:event>. So, this behaviour is fully expected.
You have 2 options:
Use #ManagedProperty instead of <f:viewParam>, or when the bean is in the view scope or broader, grab it manually from ExternalContext#getRequestParameterMap() inside #PostConstruct. And, use #PostConstruct instead of <f:event type="preRenderView">. Yes, this makes the entire <f:metadata> obsolete. You can safely remove it.
Use a JSF component instead of <c:forEach> tag, such as <ui:repeat>.
See also:
JSTL in JSF2 Facelets... makes sense?

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