Automatically set h:inputText maxlength based on Bean Validation #Size - jsf

I use JSF 2 and Hibernate Validator 5.1 in a web application.
I use the annotations like #Size or #NotNull in my beans to validate automatically my HTML forms.
It works perfectly but I would like to know if there is a way to automatically limit the number of characters typed in an input text (ie set the attribute maxlength in HTML) based on the #Size annotation.

Use maxlength attribute of <h:inputText>
You can also use f:validate -
<h:inputText id="Username" value="#{model.username}"
required="true"
label="UserName" >
<f:validateLength minimum="5" maximum="10" />
</h:inputText>

HTML5 + JSF 2.2+
If you're using HTML5 and JSF 2.2+, specify it as a passthrough attribute.
<html ... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<h:inputTextarea value="#{bean.text}" a:maxlength="2000" />

Related

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

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

JSF InputText conditional attribute render

I have a composite component (CC) that renders a inputText. I have a attribute called "autoFocus" in CC that should be rendered in inputText only when it values is true, see the code:
<composite:attribute name="myAutoFocus" default="false" type="java.lang.Boolean"/>
So, inside composite:implementation i have the following:
<h:inputText pt:autofocus="#{cc.attrs.myAutoFocus}" />
In this way my autoFocus is always enable, because "autofocus=false" and "autofocus=true" is both TRUE. So i need a way to render the autoFocus looking for my CC attribute value.
I used c:if to conditionally render the autofocus attribute via the f:passThroughAttribute from JSF 2.2 to solve my problem:
<h:inputText>
<c:if test="#{cc.attrs.myAutoFocus}">
<f:passThroughAttribute name="autofocus" value="autofocus"/>
</c:if>
</h:inputText>

Manipulate component tree in restore view phase

For a web application (myfaces 2.2), I need to reduce the component tree to speed up the application. How can I do this?
given:
a composite component that renders input elements due to a backing bean value
<h:dataTable value="#{myList}" var="myBean">
<h:column>
<h:inputText ... rendered="#{myBean.myValue == 1}" />
<h:selectOneMenu ... rendered="#{myBean.myValue == 2}">...</...>
<h:inputTextarea ... rendered="#{myBean.myValue == 3}" />
</h:column>
</h:dataTable>
problem:
all components appear in component tree, even when their rendered attribute is false
inputtext
selectOneMenu
inputTextarea
Is it possible to forbid JSF to build up the component tree with all three components? The restore view phase doesn't know about content of the apply request values phase, but it would be important to be able to interpret it still before.
If you want to achieve this behavior, try to use <c:if> tag instead of rendered atribute on JSF component
<c:if test="#{ myBean.myValue == 1 }">
<h:inputText .../>
</c:if>
don't forget to add namespace definition
xmlns:c="http://java.sun.com/jstl/core"

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!

Resources