How to set HTML5 data attribute in JSF? [duplicate] - jsf

I want to add some iOS specific tag attributes to my login-form. If I have a look on my web page source, the attributes autocorrect, autocapitalize and spellcheck aren't there. What is the reason for this? I am using JSF 2.x.
<h:inputText id="user-name" forceId="true" value="#{login.username}" style="width:120px;"
autocorrect="off" autocapitalize="off" spellcheck="false" />

This is by design. You can only specify attributes which are supported by the JSF component itself (i.e. it's listed in the attribute list in the tag documentation). You can't specify arbitrary additional attributes, they will all be plain ignored.
There are several ways to solve this:
If you're already on JSF 2.2+, simply specify it as passthrough attribute:
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
...
<h:inputText ... a:autocorrect="off" />
(note that I'm using xmlns:a instead of xmlns:p to avoid clash with PrimeFaces default namespace)
Or:
<html ... xmlns:f="http://xmlns.jcp.org/jsf/core">
...
<h:inputText ...>
<f:passThroughAttribute name="autocorrect" value="off" />
</h:inputText>
Create a custom renderer. You can find several concrete examples in below answers:
How to let JSF pass through HTML attributes
Using bootstrap related tags inside JSF2 h:inputText component
How to render a custom attribute of <h:outputLink>?
InputText PrimeFaces not applying maxlength
Adding Custom Attributes to Primefaces Autocomplete Component in JSF

Related

Accessing JSF nested composite component elements in JavaScript

I am trying to DRY up popup windows in my JSF 2 project using composite components.
This code base uses Icefaces 3.3.0 (with their 1.8.2 compatibility layer for historical reasons), Mojarra 2.2.7, and Glassfish 4.1.
I have input.xhtml which provides a text input and uses a 2-button popup (ok/cancel), which in turn builds on the basic popup.
input.xhtml:
<composite:interface>
<!-- ... -->
<composite:editableValueHolder name="forInput" targets="theInput"/>
</composite:interface>
<composite:implementation>
<my:popup2Buttons>
<ice:inputText id="theInput" value="..."/>
<script>setInputFocus("#{cc.clientId}:theInput");</script>
</my:popup2Buttons>
</composite:implementation>
popup2buttons.xhtml:
<composite:interface>
<!-- ... -->
</composite:interface>
<composite:implementation>
<my:popup>
<composite:insertChildren/>
<ice:commandButton id="OkButton"
value="Ok"
actionListener="..."/>
<ice:commandButton id="CancelButton"
value="Cancel"
actionListener="..."/>
</my:popup>
</composite:implementation>
popup.xhtml:
<composite:interface>
<!-- ... -->
</composite:interface>
<composite:implementation>
<script>
function setInputFocus(id) {
document.getElementById(id).focus();
}
</script>
<ice:panelPopup>
<f:facet name="body">
<h:panelGroup>
<composite:insertChildren/>
</h:panelGroup>
</f:facet>
</ice:panelPopup>
</composite:implementation>
The popup works mostly as expected, i.e., I can enter something, the ok and cancel buttons work, and validation works as well.
What does not work is my JavaScript code that tries to focus the input when the popup opens.
When I look at the page in Firebug, I see that the input's ID is MyForm:j_idt63:j_idt64:j_idt67:theInput, but the JavaScript code tries to focus an element with the ID MyForm:j_idt63:theInput.
Why is #{cc.clientId} in input.xhtml not the correct ID that the input ends up getting later? What do I need to do to make this work?
I've seen BalusC's hint on adding a binding but I don't want a binding so that the composite component can be independent of any backing beans.
Is there something else I am missing here?
Composite components are implicitly naming containers. I.e. they prepend their ID to the client ID of the children. This makes it possible to use multiple of them in the same view without their children causing duplicate IDs in generated HTML output.
In your specific case, you wrapped the input field in another composite which is in turn wrapped in again another composite. If you're absolutely positive that you don't need multiple naming containers wrapping in each other in this specific composition, then those (popup2buttons.xhtml and popup.xhtml) probably shouldn't be composites, but rather <ui:decorate> templates or <ui:composition> tagfiles. See also When to use <ui:include>, tag files, composite components and/or custom components?
Coming back to the technical problem, it's caused because the #{cc.clientId} does not refer the ID of the nested composite component, but of the current composite component. And thus this would be off. As to the potential solution with binding, the answer which you found does nowhere tell that you should use a backing bean for this. The binding="#{foo}" code in the answer was as-is. It really works that way, without a bean property, see also JSF component binding without bean property. However, this construct would indeed fail when you include the same composite multiple times in the same view and thus multiple components share the same binding="#{foo}". It indeed isn't supposed to be shared by multiple components, see also What is component binding in JSF? When it is preferred to be used?
To solve this without a backing bean, you can use a so-called backing component.
com.example.InputComposite
#FacesComponent("inputComposite")
public class InputComposite extends UINamingContainer {
private UIInput input;
// +getter+setter.
}
input.xhtml
<cc:interface componentType="inputComposite">
...
</cc:interface>
<cc:implementation>
...
<h:inputText binding="#{cc.input}" ... />
<script>setInputFocus("#{cc.input.clientId}");</script>
...
</cc:implementation>
The alternative is to rework them into templates or tagfiles. Be careful that you don't overvalue/overuse composites.

How to add tooltip to f:selectItems

For example the f:selectItems component doesn't support the title attribute in some versions of JSF.
Would it be possible to replace JSF Components by their plain HTML counterparts using JSFC and do something like this?
<select jsfc="h:selectOneMenu" value="#{cc.data}">
<option jsfc="f:selectItems" value="${cc.listItems}" var="item" title="#{item.tooltip}"></option>
</select>
instead of
<h:selectOneMenu value="#{cc.data}">
<f:selectItems value="#{cc.listItems}" />
</h:selectOneMenu>
Doing exactly so, replacing the latter by the above, I'm getting "<f:converter> Parent not an instance of ValueHolder: javax.faces.component.html.HtmlPanelGroup" Facelet TagExceptions
Would it be possible to replace JSF Components by their plain HTML counterparts using JSFC and do something like this
Nope. Ultimately, such a HTML element with jsfc attribute will be turned into a true JSF component in the JSF component tree and only the attributes supported by the component in question would be parsed and set as component attribute. The title attribute isn't among the supported attributes of UISelectItem component. I'm not sure what exactly you mean with "some versions of JSF". The standard JSF API already doesn't support it in first place. JSF spec issue 529 describes this shortcoming and is currently still open.
If you're using JSF 2.2, make use of passthrough attributes. You only need to replace <f:selectItems> by <c:forEach><f:selectItem>, see also Using f:selectItems var in passtrough attribute
<... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<c:forEach value="#{bean.items}" var="item">
<f:selectItem itemValue="#{item}" a:title="#{item.tooltip}" />
</c:forEach>
Based on your question history you seem to be not using JSF 2.2 yet. If you can't upgrade, you basically need a custom renderer for <h:selectOneMenu>.
While creating the custom renderer, you could make use of the unused(!) description property of the UISelectItem class. I've answered this before on a similar question targeted at <p:selectManyCheckbox>: Primefaces tooltip for p:selectManyCheckbox or other p:selectMany*/One*.
<f:selectItems ... var="item" itemDescription="#{item.tooltip}" />
Noted should be that creating the custom renderer for <h:selectOneMenu> is a pain, particularly if you intend to be JSF implementation independent. Theoretically, a custom ResponseWriter should be able to catch this, but unfortunately, the <h:selectOneMenu> only passes itself when writing <option>, instead of the UISelectItem in question.
In my case (JSF 2.2 / Mojarra 2.2.14), itemDescription worked out of the box. I.e:
<c:forEach items="#{bean.items}" var="item">
<f:selectItem itemValue="#{item}" itemLabel="#{item}" itemDescription="#{item.tooltip}" />
</c:forEach>

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!

Reusing a form in two different views JSF

Is it possible to reuse a form in two different views in JSF? I know about the ui:include but how would you do it with the action on the submit button for example? Or do I need to duplicate the forms?
When using <ui:include> you can parameterize the bean and/or the method by <ui:param>.
<ui:include src="...">
<ui:param name="bean" value="#{someBeanName}" />
<ui:param name="action" value="someMethodName" />
</ui:include>
with
<h:commandButton ... action="#{someBeanName[someMethodName]}" />
You can also make it a Facelets tag file instead so that you end up with something like
<my:someForm bean="#{someBeanName}" action="someMethodName" />
A composite component is also doable, but IMO not really the right approach for this purpose.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
Our Composite Component wiki page
You want to use composite components. Those components can be parameterized so that you could exchange the backing bean, etc..
IBM has some nice guides on that topic.
Composite components part 1 + 2 and best practices.

Null pointer Issues using the <c:if condition tag JSF Primefaces [duplicate]

I would like to output a bit of Facelets code conditionally.
For that purpose, the JSTL tags seem to work fine:
<c:if test="${lpc.verbose}">
...
</c:if>
However, I'm not sure if this is a best practice? Is there another way to achieve my goal?
Introduction
JSTL <c:xxx> tags are all taghandlers and they are executed during view build time, while JSF <h:xxx> tags are all UI components and they are executed during view render time.
Note that from JSF's own <f:xxx> and <ui:xxx> tags only those which do not extend from UIComponent are also taghandlers, e.g. <f:validator>, <ui:include>, <ui:define>, etc. The ones which extend from UIComponent are also JSF UI components, e.g. <f:param>, <ui:fragment>, <ui:repeat>, etc. From JSF UI components only the id and binding attributes are also evaluated during view build time. Thus the below answer as to JSTL lifecycle also applies to the id and binding attributes of JSF components.
The view build time is that moment when the XHTML/JSP file is to be parsed and converted to a JSF component tree which is then stored as UIViewRoot of the FacesContext. The view render time is that moment when the JSF component tree is about to generate HTML, starting with UIViewRoot#encodeAll(). So: JSF UI components and JSTL tags doesn't run in sync as you'd expect from the coding. You can visualize it as follows: JSTL runs from top to bottom first, producing the JSF component tree, then it's JSF's turn to run from top to bottom again, producing the HTML output.
<c:forEach> vs <ui:repeat>
For example, this Facelets markup iterating over 3 items using <c:forEach>:
<c:forEach items="#{bean.items}" var="item">
<h:outputText id="item_#{item.id}" value="#{item.value}" />
</c:forEach>
...creates during view build time three separate <h:outputText> components in the JSF component tree, roughly represented like this:
<h:outputText id="item_1" value="#{bean.items[0].value}" />
<h:outputText id="item_2" value="#{bean.items[1].value}" />
<h:outputText id="item_3" value="#{bean.items[2].value}" />
...which in turn individually generate their HTML output during view render time:
<span id="item_1">value1</span>
<span id="item_2">value2</span>
<span id="item_3">value3</span>
Note that you need to manually ensure the uniqueness of the component IDs and that those are also evaluated during view build time.
While this Facelets markup iterating over 3 items using <ui:repeat>, which is a JSF UI component:
<ui:repeat id="items" value="#{bean.items}" var="item">
<h:outputText id="item" value="#{item.value}" />
</ui:repeat>
...already ends up as-is in the JSF component tree whereby the very same <h:outputText> component is during view render time being reused to generate HTML output based on current iteration round:
<span id="items:0:item">value1</span>
<span id="items:1:item">value2</span>
<span id="items:2:item">value3</span>
Note that the <ui:repeat> as being a NamingContainer component already ensured the uniqueness of the client ID based on iteration index; it's also not possible to use EL in id attribute of child components this way as it is also evaluated during view build time while #{item} is only available during view render time. Same is true for an h:dataTable and similar components.
<c:if>/<c:choose> vs rendered
As another example, this Facelets markup conditionally adding different tags using <c:if> (you can also use <c:choose><c:when><c:otherwise> for this):
<c:if test="#{field.type eq 'TEXT'}">
<h:inputText ... />
</c:if>
<c:if test="#{field.type eq 'PASSWORD'}">
<h:inputSecret ... />
</c:if>
<c:if test="#{field.type eq 'SELECTONE'}">
<h:selectOneMenu ... />
</c:if>
...will in case of type = TEXT only add the <h:inputText> component to the JSF component tree:
<h:inputText ... />
While this Facelets markup:
<h:inputText ... rendered="#{field.type eq 'TEXT'}" />
<h:inputSecret ... rendered="#{field.type eq 'PASSWORD'}" />
<h:selectOneMenu ... rendered="#{field.type eq 'SELECTONE'}" />
...will end up exactly as above in the JSF component tree regardless of the condition. This may thus end up in a "bloated" component tree when you have many of them and they are actually based on a "static" model (i.e. the field does not ever change during at least the view scope). Also, you may run into EL trouble when you deal with subclasses with additional properties in Mojarra versions before 2.2.7.
<c:set> vs <ui:param>
They are not interchangeable. The <c:set> sets a variable in the EL scope, which is accessible only after the tag location during view build time, but anywhere in the view during view render time. The <ui:param> passes an EL variable to a Facelet template included via <ui:include>, <ui:decorate template>, or <ui:composition template>. Older JSF versions had bugs whereby the <ui:param> variable is also available outside the Facelet template in question, this should never be relied upon.
The <c:set> without a scope attribute will behave like an alias. It does not cache the result of the EL expression in any scope. It can thus perfectly fine be used inside for example iterating JSF components. Thus, e.g. below will work fine:
<ui:repeat value="#{bean.products}" var="product">
<c:set var="price" value="#{product.price}" />
<h:outputText value="#{price}" />
</ui:repeat>
It's only not suitable for e.g. calculating the sum in a loop. For that instead use EL 3.0 stream:
<ui:repeat value="#{bean.products}" var="product">
...
</ui:repeat>
<p>Total price: #{bean.products.stream().map(product->product.price).sum()}</p>
Only, when you set the scope attribute with one of allowable values request, view, session, or application, then it will be evaluated immediately during view build time and stored in the specified scope.
<c:set var="dev" value="#{facesContext.application.projectStage eq 'Development'}" scope="application" />
This will be evaluated only once and available as #{dev} throughout the entire application.
Use JSTL to control JSF component tree building
Using JSTL may only lead to unexpected results when being used inside JSF iterating components such as <h:dataTable>, <ui:repeat>, etc, or when JSTL tag attributes depend on results of JSF events such as preRenderView or submitted form values in the model which aren't available during view build time. So, use JSTL tags only to control flow of JSF component tree building. Use JSF UI components to control flow of HTML output generation. Do not bind the var of iterating JSF components to JSTL tag attributes. Do not rely on JSF events in JSTL tag attributes.
Anytime you think you need to bind a component to the backing bean via binding, or grab one via findComponent(), and create/manipulate its children using Java code in a backing bean with new SomeComponent() and what not, then you should immediately stop and consider using JSTL instead. As JSTL is also XML based, the code needed to dynamically create JSF components will become so much better readable and maintainable.
Important to know is that Mojarra versions older than 2.1.18 had a bug in partial state saving when referencing a view scoped bean in a JSTL tag attribute. The whole view scoped bean would be newly recreated instead of retrieved from the view tree (simply because the complete view tree isn't available yet at the point JSTL runs). If you're expecting or storing some state in the view scoped bean by a JSTL tag attribute, then it won't return the value you expect, or it will be "lost" in the real view scoped bean which is restored after the view tree is built. In case you can't upgrade to Mojarra 2.1.18 or newer, the work around is to turn off partial state saving in web.xml like below:
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
See also:
What's the view build time?
How does the 'binding' attribute work in JSF? When and how should it be used?
How to refactor snippet of old JSP to some JSF equivalent?
Should PARTIAL_STATE_SAVING be set to false?
Communication in JSF 2.0 - #ViewScoped fails in tag handlers
To see some real world examples where JSTL tags are helpful (i.e. when really properly used during building the view), see the following questions/answers:
How to make a grid of JSF composite component?
Create table columns dynamically in JSF
How to custom layout h:selectOneRadio
Conditional variable definition in JSF
How to make composite component similar to <h:selectOneRadio />
JSF 2 -- Composite component with optional listener attribute on f:ajax
Nested JSF Composite Components leading to a Stack Overflow exception
In a nutshell
As to your concrete functional requirement, if you want to render JSF components conditionally, use the rendered attribute on the JSF HTML component instead, particularly if #{lpc} represents the currently iterated item of a JSF iterating component such as <h:dataTable> or <ui:repeat>.
<h:someComponent rendered="#{lpc.verbose}">
...
</h:someComponent>
Or, if you want to build (create/add) JSF components conditionally, then keep using JSTL. It's way much better than verbosely doing new SomeComponent() in java.
<c:if test="#{lpc.verbose}">
<h:someComponent>
...
</h:someComponent>
</c:if>
See also:
Conditionally displaying JSF components
JSTL c:if doesn't work inside a JSF h:dataTable
Specify conditional rendering of element inside <ui:repeat>? The <c:if> does not seem to work
use
<h:panelGroup rendered="#{lpc.verbose}">
...
</h:panelGroup>
For switch-like output, you can use the switch face from PrimeFaces Extensions.

Resources