How to pass rich params to jsf for i18n? - jsf

I am using jsf to render my html pages and I am using the nifty resource bundle loading to add i18n to the various pages. The problem I am having is that with outputFormat you can not pass in any "rich" parameters. For instance this sentance:
This my favorite search engine, you should check it out.
It would be nice to do something like this:
<h:outputFormat value="#{bundle.favItemLineWithParam}>
<f:param>
<h:outputFormat value="#{bundle.searchEngine}>
<f:param>
<h:link value="http://google.com">
</f:param>
</h:outputFormat>
</f:param>
</h:outputFormat>
but that is not allowed, it would seem like the only option is to render the links in java with a backing bean or something. Any Ideas?

That's not possible. You need to use plain HTML in the bundle value and set escape="false".
favItem = This is my favourite {0}, you should check it out.
with
<h:outputFormat value="#{bundle.favItem}" escape="false">
<f:param value="search engine" />
<f:param value="http://google.com" />
</h:outputFormat>
Update:
Since version 1.5, it's possible with <o:param> of JSF utility library OmniFaces:
favItem = This is my favourite {0}, you should check it out.
searchEngine = search engine
with
<h:outputFormat value="#{bundle.favItem}" escape="false">
<o:param>#{bundle.searchEngine}</o:param>
</h:outputFormat>

Related

Passing dynamic param through bundle.properties to alt text value of graphicImage [duplicate]

I have use case in which I have to use resource bundle to display various texts on UI. Some of these resource bundle entries take paramets (e.g. {0}), for these I use h:outputFormat but sometimes that isn't enough.
e.g.
someMessage=Display this message with param {0}
in a resource bundle.
To display it on xhtml I normally do:
<h:outputFormat value="#{msg['someMessage']}"><f:param value="#{someBean.value}"/></h:outputFormat>
That works well when it's a simple case, but for more complex use cases it isn't enough. For example if I want the 'title' attribute of a commandLink to use the above resource bundle entry:
<h:commandLink action="logout" title="#{msg['someMessage']}">
<f:param value="#{someBean.value}" />
<h:graphicImage library="images" name="image.png" />
</h:commandLink>
which doesn't work. I also tried:
<h:commandLink action="logout">
<f:attribute name="title">
<h:outputFormat value="#{msg['someMessage']}"><f:param value="#{someBean.value}"/></h:outputFormat>
</f:attribute>
<h:graphicImage library="images" name="image.png" />
</h:commandLink>
which also doesn't work since f:attibute doesn't allow children.
Even if there is a hack to bypass this (e.g. using hover component from primefaces) there are other fields that might require a parameterized message.
Does anyone know of a way to use MessageFormat that takes an argument in a non-value field of a JSF component?
You could create a custom EL function for this with which you can ultimately end up like:
<h:commandLink ... title="#{my:format(msg['someMessage'], someBean.value)}" />
You can use the MessageFormat API to perform the job, exactly as <h:outputFormat> is doing under the covers.
An alternative is to create a custom component which does the same as JSTL's good 'ol <fmt:message> which supports a var attribute to export the formatted message into the EL scope.
<my:outputFormat ... var="linkTitle">
...
</my:outputFormat>
<h:commandLink ... title="#{linkTitle}" />
Update: JSF utility library OmniFaces has #{of:formatX()} functions and a <o:outputFormat> component for the very purpose.

Does PrimeFaces has anything like o:param (solution to add complex parameter for outputFormat)?

The given problem is that passing complex parameter (see code example below) doesn't work in JSF.
<h:outputFormat value="Final result is: {0}">
<f:param>
<h:outputFormat value="{0} to {1}">
<f:param value="#{mngr.lowerBound}"/>
<f:param value="#{mngr.upperBound}"/>
</h:outputFormat>
</f:param>
</h:outputFormat>
I'm NOT looking for the solution that uses the ManagedBean, like this:
<h:outputFormat value="Final result is: {0}">
<f:param value="mngr.formattedParams />
</h:outputFormat>
However there is a proper solution that works in OmniFaces:
JSF-2. h:outputFormat. Complex f:param
I'm wondering if there is also a solution in PrimeFaces?
No PrimeFaces does not have this. There is no reason to either since OmniFaces has it. And they both target different aspects of JSF: ui component suite vs utility suite so fully complementary

How to use JSF navigation rules with ResourceBundle content

I have a multi-lingual site with content managed by ResourceBundles. How can I use JSF navigation to insert links to website sections using paragraph content.
Example 1: Desired HTML output
<p>Simply contact us to find out more.</p>
Example 2: Simple facelt to achieve the above
<p>Simply <h:link outcome="contact" value="contact us"/> to find out more.</p>
Desired result: Same but with ResourceBundle
Facelet
<p>
<h:outputText value="${template['paragraph']}">
<f:param>
<h:link outcome="contact" value="${template['contactUs']}"/>
</f:param>
</h:outputText>
</p>
ResourceBundle
paragraph=Simply {0} to find out more.
contactUs=contact us
The problem is not exactly the JSF navigation rules, but that you cannot use <f:param> to specify JSF components as bundle parameter, let alone plain vanilla HTML children. Also, please note that you cannot use <f:param> in <h:outputText>, but only in <h:outputFormat>.
In order to achieve the functional requirement anyway, you've to write down the HTML in escaped flavor as <f:param value> yourself.
<h:outputFormat value="#{template['paragraph']}" escape="false">
<f:param value="<a href='#{request.contextPath}/contact.xhtml'>#{template['contactUs']}</a>" />
</h:outputFormat>
or, if you'd like to utilize JSF ViewHandler#getBookmarkableURL() like as <h:link> is doing for its outcome attribute,
<h:outputFormat value="#{template['paragraph']}" escape="false">
<f:param value="<a href='#{facesContext.application.viewHandler.getBookmarkableURL(facesContext, '/contact', null, false)}'>#{template['contactUs']}</a>" />
</h:outputFormat>
Since you're not the first one who stumbled upon this and the workarounds are awkward, the JSF utility library OmniFaces has recently updated its <o:param> component with support to encode children as param value when no value is specified. From OmniFaces 1.5 on, you should be able to use it as follows:
<h:outputFormat value="#{template['paragraph']}" escape="false">
<o:param><h:link outcome="contact" value="#{template['contactUs']}" /></o:param>
</h:outputFormat>

Passing EL method expression as attribute of custom Facelets tagfile

I created a custom JSF tag:
<ui:composition>
<h:panelGroup>
<rich:dataScroller id="#{id}" for="#{table}" execute="#{table}"
page="#{scrollerPage}" render="#{table}-sc1" maxPages="5"
fastControls="hide" oncomplete="#{onCompl}" scrollListener="#{scrollListenerBean[scrollListenerMethod]}" />
<h:inputText value="#{scrollerPage}" id="#{table}-sc1" size="2">
<f:convertNumber integerOnly="true" />
</h:inputText>
<h:outputText styleClass="outputText"
value=" of #{scrollPagesCount} " />
<h:commandButton value="GO! " />
</h:panelGroup>
</ui:composition>
To pass the listener method, I used the solution suggested in a quite old blog:
<my:dataScroller id="idDS1" table="table1"
scrollerPage="#{bean.navigationHelper.scrollerPage}"
scrollPagesCount="#{bean.navigationHelper.scrollPagesCount}"
onCompl="initForm();"
scrollListenerBean="#{bean}"
scrollListenerMethod="aMethod" />
My questions are: is this the best way to do this? How can I make the method optional?
Thanks a lot for any Help! bye!
My questions are: is this the best way to do this?
That's the only way anyway, provided that you can only use standard JSF/EL facilities and you cannot create a custom taghandler.
You could however create a custom taghandler to convert the value expression to a method expression. The OmniFaces JSF utility library has a <o:methodParam> for exactly this purpose. See also the <o:methodParam> demo page.
You could then end up like:
<my:dataScroller ... scrollListener="#{bean.aMethod}" />
and
<o:methodParam name="scrollListenerMethod" value="#{scrollListener}" />
<rich:dataScroller ... scrollListener="#{scrollListenerMethod}" />
See also:
Dynamic ui include and commandButton
How can I make the method optional?
Theoretically, you could use JSTL tags to build the view conditionally. Something like:
<h:someComponent>
<c:if test="#{not empty fooAttribute}">
<f:attribute name="foo" value="#{fooAttriubte}" />
</c:if>
</h:someComponent>
But that's in the particular case of a special method expression listener attribute unfortunately not possible. There's no such thing as <rich:scrollListener> or something which allows you binding a RichFaces specific scrollListener as a separate tag to the <rich:dataScroller>. Best what you could do without creating custom taghandlers is duplicating the whole <rich:dataScroller> in two <c:if>s (or a <c:choose>); one with and other without scrollListener. This is too clumsy. You'd really better create a custom <my:richScrollListener> taghandler for this which you could then place in a <c:if>.

JSF converter for f:param

I'm using dynamically created links:
<h:link outcome="/page" value="#{name}">
<f:param name="name" value="#{name}"/>
</h:link>
I would like to attach custom converter for f:param to remove spaces from #{name} etc.
But there is no converter property in f:param.
A Converter is intented to convert from submitted String request parameter values to complex objects and vice versa in input fields. However, the <f:param> is pure output only and it will always call toString() on the value. It doesn't support a Converter.
Your cleanest and best bet is to create a custom EL function, so that you ultimately end up like:
<f:param name="name" value="#{util:prettyUrl(name)}"/>
Update: the JSF utility library OmniFaces has since version 1.4 (March 2013) a <o:param> component which extends the <f:param> with support for a fullworthy JSF converter, exactly like as you'd use in <h:outputText converter>.
<h:link outcome="/page" value="#{name}">
<o:param name="name" value="#{name}" converter="somePrettyURLConverter" />
</h:link>
See also the showcase.
what if you do something like this?
<f:param name="name" value="#{name.replace(' ', '')}" />
Isn't this working?
Or you want for all < f:param ... ??
Regards

Resources