JSF2.0 Composite Component ID generation - jsf

I'm in the process of creating a new Web Application using JSF2.0 on Weblogic 11g. I'm using JSF Ajax for form submission. I'm quite new to JSF so still learning the ropes. The main page has 3 forms each on a jQuery tab. The original code had a lot of duplicate Input Fields like userName and password etc (id prepended with the form id i.e. myform1:userName). I decided it would be a good idea to use Composite Components for the duplicated fields. Here is my Conponent code:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:composite="http://java.sun.com/jsf/composite"
xmlns:h="http://java.sun.com/jsf/html">
<composite:interface>
<composite:attribute name="value" required="true"/>
</composite:interface>
<composite:implementation>
<label for="#{cc.id}">User Name</label>
<h:inputText
id="#{cc.id}"
size="15"
value="#{cc.attrs.value}"
required="true"
label="User Name">
</h:inputText>
</composite:implementation>
</html>
And here is the call to the Component in the xhtml:
<p>
<cc:userName id="userName" value="#{soapTestingBackingBean.userName}"/>
</p>
The problem now is that all my ids have an added element so have become myForm1:userName:userName. Although this isn't a show stopper it does mean that my javascript now has to reference the long ids and is also the same in my Ajax calls (I generally execute #form but render specific elements). I'm trying to make the code as readable and maintainable as possible. So would appreciate it if anyone knew if there were an elegant work around for this or maybe some magic attribute I missed to turn it off. I did experiment with the forceID attribute from the tomahawk library but this just caused additional problems on my Ajax calls. Thanks.

some java script libraries jQuery are having problem with the new format for jsf 2.0 ids form:elementId - so instead of using
$(function() {
$( "#datepicker" ).datepicker();
});
I had to use
$(function() {
$(document.getElementById('addform:datepicker')).datepicker();
});

Related

Saving and reusing tag definition in PrimeFaces

Let's say I have the following construct polluting the simplicity of my JSF code in many places:
<p:calendar id="decisionDate"
effect="explode"
yearRange="2000:2100"
pattern="MM/dd/yyyy"
navigator="true" display="inline"
value=""
label="Decision Date"
maxlength="10"
size="20">
<f:convertDateTime pattern="MM/dd/yyyy" />
</p:calendar>
As can be seen, this has nine (9) attributes and a nested tag. This is an awful amount of tedious detail to consume with your eye.
Is there a way I can reuse PrimeFaces tags in a similar way as CSS: to save a complex tag definition as <px:myCalendar/> with the above parameters minus the ID ones, which should be set for each instance of use nonetheless, where px would be my namespace and then each time I need to invoke it, I would just say <px:myCalendar id="uniqueCalID"/> and ... BOOM ... there goes all the repeated clutter?
POST ANSWER EDIT: Check out this tutorial
You can define composite component. It is defined with xhtml+ jsf namespaces and, but in your case it is unnesessary, backing component, which is java class, instantiated for every composite component usage.
Within composite component interface you can define attributes, which vary its behaviour. And in implementation you then can insert needed primefaces' component with some hardcoded attributes and some passed from your composite component invocation.
Consider this tutorial: https://docs.oracle.com/javaee/6/tutorial/doc/giqzr.html
Example
Composite component is resource, so we put it below /resources folder. Let's create subfolder /resources/myCompositeComponents and create xhtml file myCalendar.xhtml there. It will be our composite component. Basically, it is xhtml file with additional namespace xmlns:cc="http://java.sun.com/jsf/composite". Here is the code. You can notice two elements: <cc:interface> and <cc:implementation>. And <cc:attribute> element inside the <cc:interface> is the input of our composite component.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:cc="http://java.sun.com/jsf/composite"
xmlns:p="http://primefaces.org/ui" xmlns:h="http://java.sun.com/jsf/html">
<cc:interface>
<cc:attribute name="label" default="Decision Date"/>
</cc:interface>
<cc:implementation>
<h2>#{cc.clientId}</h2>
<h:outputLabel
id="Label"
value="#{cc.attrs.label}"/>
<p:calendar id="Calendar"
effect="explode"
yearRange="2000:2100"
pattern="MM/dd/yyyy"
navigator="true" display="inline"
value=""
label="Label"
maxlength="10"
size="20">
<f:convertDateTime pattern="MM/dd/yyyy" />
</p:calendar>
</cc:implementation>
</html>
Then, let's use it. To be able to declare our brand new component we will put additional namespace into the using page: xmlns:my="http://java.sun.com/jsf/composite/myCompositeComponents". The last part of the namespace uri corresponds to the folder under /resources, where composite component lives. Give it any prefix you like. Here is source code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:my="http://java.sun.com/jsf/composite/myCompositeComponents">
<h:head>
<title>Simple JSF Facelets page</title>
</h:head>
<h:body>
<my:myCalendar id="LetsUseIt" label="MyLabel"/>
</h:body>
</html>
Have a notice of attribute "label" - that very attribute, that is declared in the "interface" element.
This is quite basic usecase, though it will help in your situation. More complex scenarios include passing typed attributes and implementing backing component - java class, instantiated every time the component is used.

Nested JSF composite components not fully compatible with Primefaces

I'm trying to create a nested JSF composite control wrapped in a Primefaces Accordion control. However when the tab components are placed within the nested component they are not rendered at all.
outerComponent.xhtml
<composite:interface/>
<composite:implementation>
<p:accordionPanel>
<composite:insertChildren/>
</p:accordionPanel>
</composite:implementation>
innerComponent.xhtml
<composite:interface>
<composite:attribute name="title" type="java.lang.String"/>
</composite:interface>
<composite:implementation>
<p:tab id="#{cc.attrs.title}" title="#{cc.attrs.title}">
Some content
</p:tab>
</composite:implementation>
testPage.xhtml
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:w="http://java.sun.com/jsf/composite/wizard"
xmlns:p="http://primefaces.org/ui">
<h:head>
</h:head>
<h:body>
<w:outerComponent>
<w:innerComponent title="tab1"/>
</w:outerComponent>
</h:body>
</html>
HTML output:
<html xmlns="http://www.w3.org/1999/xhtml"><head><link type="text/css"
rel="stylesheet" href="/iip/javax.faces.resource/theme.css.xhtml?ln=primefaces-
aristo-custom" /><link type="text/css" rel="stylesheet" href="/iip/
javax.faces.resource/primefaces.css.xhtml?ln=primefaces" /><script type="text/
javascript" src="/iip/javax.faces.resource/jquery/jquery.js.xhtml?
ln=primefaces"></script><script type="text/javascript" src="/iip/
javax.faces.resource/primefaces.js.xhtml?ln=primefaces"></script></head>
<body>
<div id="j_idt7:j_idt10" class="ui-accordion ui-widget ui-helper-reset ui-hidden-
container" role="tablist"><input type="hidden" id="j_idt7:j_idt10_active"
name="j_idt7:j_idt10_active" value="0" /></div>
<script id="j_idt7:j_idt10_s" type="text/
javascript">PrimeFaces.cw('AccordionPanel','widget_j_idt7_j_idt10',
{id:'j_idt7:j_idt10'});</script>
</body</html>
When it runs there are no errors and while the Accordion divs are rendered, the tabs are not. However if I move the <p:tab> tags into the outerComponent.xhtml file then they are rendered correctly, but that is not what I require.
Any suggestions?
Iterating components like <p:dataTable>, <p:tabView>, <p:accordionPanel>, etc cannot have composites as direct children. They should have fullworthy <p:column> or <p:tab> components as direct children. While iterating during view render time, they loop over children and do an instanceof UIColumn or instanceof Tab check on them before rendering. If it fails (the composite is NamingContainer), then it would be plain ignored. This is "by design".
Your best bet is using a tag file instead of a composite component as child of an iterating component.
Note that this isn't specfic to PrimeFaces. Standard <h:dataTable> has exactly the same problem.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
How to create a composite component for a datatable column?
Did you try to do this without composite - I mean put it all together in the testPage.xhtml. I haven't tried this specific combination but I've had problems with both tab and accordion in combination with other components. To check if the problem lies in the composite or in the combination of components.
It seems that there are some javascript that is "not compatible" with one another.
If you still have the problem, you could try to encapsulate the tab. I tried different combinations and it seems that some are working depending on which components are causing the problem. I'd try with a <div id="tabContainer"> around the tab first and eventually go to p:panel if it doesn't work.

param reference to bean not being passed into composite component

i'm having a bit of trouble with a composite component in JSF 2.1 vanilla (on glassfish 3.1). the simplified version of my problem is here:
[composite component]
<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:p="http://primefaces.org/ui"
xmlns:cc="http://java.sun.com/jsf/composite">
<!-- INTERFACE -->
<cc:interface>
<cc:attribute name="value" required="true"/>
<cc:attribute name="title" required="false" default=""/>
<cc:editableValueHolder name="inputTarget" targets="labeledInputField"/>
</cc:interface>
<!-- IMPLEMENTATION -->
<cc:implementation>
<p:inputText id="labeledInputField"
label="#{cc.attrs.title}"
value="#{cc.attrs.value}"
title="#{cc.attrs.title}">
<cc:insertChildren/>
</p:inputText>
</cc:implementation>
</html>
[implemented in]
<!-- thisPerson is passed in via ui:param to the facelet containing this code.
it works in other (non-composite) components on the page -->
<comp:labeledInputText
id="baseUsername"
value="#{controller.username}"
title="#{bundle.Username}">
<f:validator for="inputTarget" binding="#{thisPerson.usernameValidator}"/>
<f:converter for="inputTarget" converterId="#{whiteSpaceTrimConverter}"/>
</comp:labeledInputText>
the problem is, the "thisPerson.usernameValidator" is evaluating to NULL, which then causes the com.sun.faces.facelets.tag.jsf.ValidatorTagHandlerDelegateImpl to then skip to the code that attempts to load the validator by "validatorID" which is not set because we're trying to send in the validator by "binding". is there a way to get the composite to evaluate the ui:param value, or a workaround that does not require reworking the validator (it's a huge anti-pattern and i don't have time to reverse the damage right now). assume the validator HAS to come in via binding.
i know the composite works because in a different facelet, i have the validator binding against a concrete bean reference, rather than a "soft" reference, and it works like a champ.
TIA
Without knowing your exact JSF implementation, I am going to assume Mojarra, you may be running into the following known bug.
http://java.net/jira/browse/JAVASERVERFACES-2040
Regardless if this is your exact problem or not, you can try to disable partial state saving and see if this resolves your issue. If it does then that means that you are facing this issue, which apparently was (fixed?) in later versions of Mojarra.
Another possibility would be to simply use renderFacet instead of insertChildren and insert your validators in the form of a facet.

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!

How to create a composite of existing components in JSF?

I'd like to know if it's possible to compose my own component (or call it Widget, Object).
I mean, instead of (for example) using h:panelGroup and a h:outputLabel inside it, make my own h:panelMarkzzz, as a composition of panelGroup and outputLabel.
Is it possible on JSF?
Yes, it's possible to create a composition of existing components like that.
Kickoff example:
/resources/foo/group.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:cc="http://xmlns.jcp.org/jsf/composite">
<cc:interface>
<cc:attribute name="label" type="java.lang.String" required="true" />
</cc:interface>
<cc:implementation>
<h:panelGroup>
<h:outputLabel value="#{cc.attrs.label}" />
<cc:insertChildren />
</h:panelGroup>
</cc:implementation>
</html>
/test.xhtml
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:foo="http://xmlns.jcp.org/jsf/composite/foo">
<h:head>
<title>Test</title>
</h:head>
<h:body>
<foo:group label="Label value">
<h:outputText value="This will appear after label inside the panelgroup" />
</foo:group>
</h:body>
</html>
The /foo folder name is free to your taste and you can reference it in XML namespace as http://xmlns.jcp.org/jsf/composite/XXX. The XHTML filename is the tag name.
That said, composite components have performance implications and they should only be used when the functional requirement is not achievable using a simple include or tagfile. In your specific case, you'd better use a tagfile instead. A composite component is only worthy when you actually need it for the <cc:interface componentType="...">.
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
Our composite component wiki page
JSF http://xmlns.jcp.org/jsf/composite tag documentation
Java EE 7 tutorial - Composite components
Java EE 7 tutorial - Advanced composite components
Perhaps you mean Composite Components?

Resources