Send array list via ui:param to JSF ui:composition template - jsf

I know i can use ui:param to pass a string from a composition built upon a template
Like this: http://www.mkyong.com/jsf2/how-to-pass-parameters-to-jsf-2-0-template-file/
Then I can use the parameter in the XHTML for the template file.
Can you send an array?
I.e.
<ui:insert name="header" >
<ui:include src="/template/common/commonHeader.xhtml">
<ui:array name="tagArray" values="val1, val2, val3" />
</ui:include>
</ui:insert>

Only if your environment supports EL 3.0 (Tomcat 8, WildFly 8, GlassFish 4, etc and newer). You can the use the new list notation #{[x,y,z]}.
<ui:array name="tagList" values="#{['val1', 'val2', 'val3']}" />
If you're not on EL 3.0 yet, then your best bet is using JSTL fn:split() to split a delimited string to an array.
<ui:param name="tagArray" value="#{fn:split('val1,val2,val3', ',')}" />

Related

Do I have to pass ui:param in template if I am using ui:composite and ui:insert, ui:include?

I have one page main.xhtml, which contains ui:composition. This composition uses template1.xhtml file. template1.xhtml file contains ui:insert, ui:include tag which are pointing to template2.xhtml file. Now, I want to use parameters that are passed from ui:composition inside template2.xhtml.
main.xhtml
<ui:composition template="template1.xhtml">
<ui:param name="a1" value="val1"/>
</ui:composition>
template1.xhtml
<ui:insert name="header">
<ui:include src="template2.xhtml">
</ui:insert>
template2.xhtml
<h:panelGroup rendered="#{not empty a1}" layout="block">
<h4>#{a1}</h4>
</h:panelGroup>
My question is can I directly access parameter named a1 or I had to again pass ui:param in ui:include?
Depends on Facelets version and JSF impl/version.
In original Facelets 1.x, any <ui:param> in parent composition is inherited into all <ui:include> children.
<ui:include src="template2.xhtml" />
In Facelets 2.x as integrated in JSF 2.x, any <ui:param> of a parent composition which ought to be reused in an <ui:include> (or <ui:decorate>) must be explicitly passed through.
<ui:include src="template2.xhtml">
<ui:param name="a1" value="#{a1}" />
</ui:include>
At least, that's the case when you're using Mojarra 2.x. In MyFaces 2.0 / 2.1, however, it was not necessary as the original Facelets 1.x behavior unintentionally slipped into MyFaces 2.0 / 2.1.
<ui:include src="template2.xhtml" />
They have fixed it in MyFaces 2.2, so you need to explicitly pass them through.
<ui:include src="template2.xhtml">
<ui:param name="a1" value="#{a1}" />
</ui:include>
In case you're using MyFaces 2.2 or newer, and want to retain the original Facelets 1.x behavior, then you can add the following context param to web.xml:
<context-param>
<param-name>org.apache.myfaces.STRICT_JSF_2_FACELETS_COMPATIBILITY</param-name>
<param-value>true</param-value>
</context-param>
<ui:include src="template2.xhtml" />
No such context param exist for Mojarra, so this should not be relied upon in case you want to have your code to work the same across all JSF implementations.

Reuse some .xhtml pages on a JSF primefaces application

I developing a simple application using JSF and PrimeFaces and here's a problem that I'm facing:
These are managed beans that have a Person property:
ClientBean
EmployeeBean
I have the person.xhtml that shows the data from a person. I include the person.xhtml on a client.xhtml and employee.xhtml. I need to create two person.xhtml because I'm using different beans. What I want to do is something like that:
<c:set var="person" value="clientBean.person" />
<ui:include src="person.xhtml"/>
<c:set var="person" value="employeeBean.person" />
<ui:include src="person.xhtml"/>
And in my person.xhtml I can use #{person.name} , #{person.dateOfBirth}.
I searched and use <c:set/> in JSF is wrong.
Anyone can help?
Pass it as <ui:param>.
<ui:include src="person.xhtml">
<ui:param name="person" value="#{clientBean.person}" />
</ui:include>
<ui:include src="person.xhtml">
<ui:param name="person" value="#{employeeBean.person}" />
</ui:include>
Register person.xhtml if necessary as a tag file to make it look better, see also When to use <ui:include>, tag files, composite components and/or custom components?
<my:personForm value="#{clientBean.person}" />
<my:personForm value="#{employeeBean.person}" />
Beware of duplicate component ID errors. See also Avoiding duplicate ids when reusing facelets compositions in the same naming container.

How can I pass a list literal to f:selectItems?

For example:
<h:selectManyCheckbox
id="literalOptions"
value="firstOption">
<f:selectItems value="[firstOption, secondOption, thirdOption]"/>
</h:selectManyCheckbox>
this doesn't work, but you get the idea?
I want to pass literal (string-type) list options (not necessarily but possibly retrieved from a bean property as a String), the [a,b,c] list-syntax probably isn't correct, but which is?
Or, alternatively, how can I pass a list literal to a custom component I create that passes this literal to f:selectItems which I use internally in my custom component? That is, how can I create a custom component that accepts such a literal for ad hoc definition of list values by the component user.
If you're on Java EE 6, use JSTL fn:split() trick.
<html ... xmlns:fn="http://java.sun.com/jsp/jstl/functions">
...
<h:selectManyCheckbox value="firstOption">
<f:selectItems value="#{fn:split('firstOption,secondOption,thirdOption', ',')}"/>
</h:selectManyCheckbox>
If you're on Java EE 7, use EL 3.0 collection literal.
<h:selectManyCheckbox value="firstOption">
<f:selectItems value="#{['firstOption', 'secondOption', 'thirdOption']}"/>
</h:selectManyCheckbox>
You was close, you just had to quote the string values and to put the whole in #{...}.
Note that specifying a literal in <h:selectManyCheckbox value> would fail with a PropertyNotWritableException on submit, but that's a different problem.

How to add placeholder attribute to JSF input component?

Shouldn't this line of code render a inputtext field with the placeholder text "fill me" when using html5?
<h:inputText placeholder="fill me" />
I do not see any placeholder text. I thought everything that was not JSF was passed to the browser for rendering?
I thought everything that was not JSF was passed to the browswer for rendering?
This assumption is thus wrong. Unspecified component attributes are ignored by the JSF renderers.
You have basically the following options to get it to work:
If you're already on JSF 2.2 or newer, set it as a passthrough attribute.
<... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:inputText a:placeholder="fill me" />
Note that I use a XML namespace prefix of a ("attribute") instead of p as shown in the tutorial, as it would otherwise clash with default XML namespace prefix p of PrimeFaces.
Implement a custom renderer for <h:inputText> wherein you explicitly check and write the attribute.
Implement a custom component which uses the aforementioned custom renderer.
Implement a JS based solution wherein you grab the element from DOM and explicitly set the attribute.
Look for a component library which supports this out the box. PrimeFaces for example has a <p:watermark> for this purpose with nice JS based graceful degradation for browsers which does not support the placeholder attribute on inputs.
See also:
Custom HTML tag attributes are not rendered by JSF
You can achieve it either with placeholder attribute or with p:watermark if using Primefaces and JSF 2.0+ or, when JSF 2.2 available, you can use pt:placeholder attribute.
Primefaces
<p:inputText id="search_input_id" value="#{watermarkBean.keyword}"
required="true" label="Keyword" placeholder="fill me" />
Legacy browser support (Adds JS solution):
<p:inputText id="search_input_id" value="#{watermarkBean.keyword}"
required="true" label="Keyword" />
<p:watermark for="search_input_id" value="fill me" />
JSF 2.2 (without PF)
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:pt="http://xmlns.jcp.org/jsf/passthrough">
<h:head>
</h:head>
<h:body>
<h:inputText value="#{bean.value}" pt:placeholder="fill me"/>
</h:body>
</html>
Which basically generates an HTML 5
<input placeholder="fill me" />
Check out this answer.
With JSF 2.2 you can passthrough unspecified attributes like this:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:p="http://xmlns.jcp.org/jsf/passthrough"
>
<h:inputText p:placeholder="fill me"></h:inputText>
In case you are using RichFaces, starting in version 4.3, you can use the tag "rich:placeholder" for this purpose as shown here. Basically:
<h:inputText id="myInput">
<rich:placeholder value="My placeholder text"></rich:placeholder>
</h:inputText>
Try this
<h:inputText id="name" value="#{login.userId}" class="aux1" />
<h:inputSecret id="password" value="#{login.password}" redisplay="true" class="aux2" autocomplete="off" />
<script>
$('.aux1').attr('placeholder', 'Introducir Usuario');
$('.aux2').attr('placeholder', 'Introducir ContraseƱa');
</script>
With jQuery, this works right for me.
It's very easy and browser independent code as BaluSc told,
In primefaces, use p:watermark to get the required functionality.
Official Demo is HERE
Use primeface 4.0. Versions below this version do not support the placeholder attribute.
use name space xmlns:pt="http://java.sun.com/jsf/passthrough".
p:inputTextarea id="textAreaValue" pt:placeholder="your text"
don't insert a new line in inputTextArea.
The simplest way to render an input field with a placeholder text is to use the elementary input tag
Example:
<input type="text" placeholder="Fill me" value="#{EL}"/>
Note: you dont have to include any namespaces
<h:head>
</h:head>
<h:body>
<h:inputText value="#{bean.value}" placeholder="fill me"/>
</h:body>
This works right for me, try it!

String concatenation in EL for dynamic ResourceBundle key

I have a resource bundle with entries like these:
entry1=value1
entry2=value2
entry3=value3
In my JSF page I'm trying to use these keys dynamically. The ID of the entry is coming from a managed bean. I think it should be something like this:
<h:outputText value="#{msg['entry' managedBean.entryIndex]}"/>
How can I achieve this?
If you're already on Servlet 3.1 / EL 3.0 (Tomcat 8, WildFly 8, GlassFish 4, etc), make use of new EL 3.0 += operator:
<h:outputText value="#{msg['entry' += managedBean.entryIndex]}" />
If you're only on Servlet 3.0 / EL 2.2 (Tomcat 7, JBoss AS 6/7, GlassFish 3, etc), make use of new EL 2.2 ability to directly invoke methods such as String#concat():
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}" />
If you're even not on Servlet 3.0 / EL 2.2 yet, make use of <c:set> to create another variable with the desired EL expression inlined:
<c:set var="key" value="entry#{managedBean.entryIndex}" />
<h:outputText value="#{msg[key]}" />
This should solve your issue:
<h:outputText value="#{msg['entry'.concat(managedBean.entryIndex)]}"/>
Here's what worked for me : concat outside of []
<h:outputText value="#{msg['entry'].concat(managedBean.entryIndex)}" />
I think you'll have to write a facelets function concat(str1, str2).

Resources