The validator for an input field inside a composite component never starts

I created several Facelets to make it easier to design our pages. In particular, I created a series of Facelets for input components. I have 1 Facelet, <xxx:input /> , which displays a label around the input field. In addition, I have Facelets, such as <xxx:inputText /> and <xxx:inputSecret /> , which display the actual input field. Each of them uses <xxx:input /> to display the label. Facelet looks something like this:

 <html ...> <composite:interface> ... </composite:interface> <composite:implementation> <label><h:outputText value="#{cc.attrs.labelText}" /></label> <composite:insertChildren /> </composite:implementation> </html> 

The front side of <xxx:inputText /> will look like this:

 <html ...> <composite:interface> ... </composite:interface> <composite:implementation> <xxx:input labelText=...> <h:inputText id="myinput" ... /> </xxx:input> </composite:implementation> </html> 

Everything turns out fine, but I'm having trouble trying to add <f:validator /> or other validation tags. From what I read, I need to add a tag to my Facelet. So, I added the line <composite:editableValueHolder name="myinput" targets="myinput" /> in the interface section. However, I still do not see my validator being fired. I have something similar in my .xhtml file ...

  ... <xxx:inputText value="..."> <f:validateLength minimum="10" for="myinput" /> </xxx:inputText> ... 

Regardless of the input I entered, the validator never fires, and I never get an error message. The employee suggested that this is due to the target identifier that I am using and the fact that it is wrapped in <xxx:input /> Facelet.

Do I need to include the identifier of the parent component in my target definition? Is there anything else I am missing? It works fine if I exclude <xxx:input /> Facelet, so I assume this is related to this, but don't know how to solve it. Any help you can provide is SO appreciated.

+7
source share
1 answer

You need to specify the for attribute of the validator so that it matches name <composite:editableValueHolder> .

 <xxx:inputText value="..."> <f:validateLength for="myinput" minimum="10" /> </xxx:inputText> 

You also need to make sure that <composite:editableValueHolder> is specified in both composites, as well as input.xhtml . Here is a complete example that works great for me on Mojarra 2.1.12:

/resources/components/input.xhtml :

 <ui:component xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:cc="http://java.sun.com/jsf/composite" > <cc:interface> <cc:attribute name="label" required="true" /> <cc:editableValueHolder name="input" targets="input" /> </cc:interface> <cc:implementation> <h:outputLabel for="input" value="#{cc.attrs.label}" /> <cc:insertChildren /> </cc:implementation> </ui:component> 

/resources/components/inputText.xhtml :

 <ui:component xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:cc="http://java.sun.com/jsf/composite" xmlns:my="http://java.sun.com/jsf/composite/components" > <cc:interface> <cc:attribute name="label" required="true" /> <cc:attribute name="value" required="true" /> <cc:editableValueHolder name="input" targets="input:text" /> </cc:interface> <cc:implementation> <my:input id="input" label="#{cc.attrs.label}"> <h:inputText id="text" value="#{cc.attrs.value}" /> </my:input> </cc:implementation> </ui:component> 

Usage in some test.xhtml :

 <!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:my="http://java.sun.com/jsf/composite/components" > <h:head> <title>SO question 12188638</title> </h:head> <h:body> <h:form> <my:inputText label="foo" value="#{bean.input}"> <f:validateLength minimum="10" for="input" /> </my:inputText> <h:commandButton value="submit" action="#{bean.submit}"> <f:ajax execute="@form" render="@form"/> </h:commandButton> <h:messages/> </h:form> </h:body> </html> 

See also:


Unrelated to a specific problem, do you know about <h:outputLabel> ?

 <h:outputLabel value="#{cc.attrs.labelText}" /> 

And the fact that you can simply insert EL into the template text without the explicit need for <h:outputText> ?

 <label>#{cc.attrs.labelText}</label> 

Did you notice that your label also lacks the for attribute, which should refer to the identifier of the input element that the label should refer to?

 <h:outputLabel for="someId" ... /> <h:inputText id="someId" ... /> 
+9
source

All Articles