Saving and reusing tag definition in PrimeFaces - jsf

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.

Related

JSF2 EL html output

Background
I have an existing web application that relies on JSF2. In most pages, there are expressions that output text from various property files. Some properties might contain html. However, JSF expressions escape html into plain text. The solution I found was to use <h:outputText> with escape set to false. Using this would be cumbersome due to amount of expressions that would need to be wrapped.
Question
My question is, is there a way to configure all expressions to not escape html?
If I were you I would create my own composite component wich can be called In xhtml with
<myComponents:outputText value="<STRONG>the html taged value</STRONG>">
Simply add this custom component in a new xhtml file in the defaut jsf folder src/webapp/components.
Like :
src/webapp/components/myComponents/outputText.xhtml
<!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
<cc:attribute name="value" required="true"/>
</cc:interface>
<cc:implementation>
<h:outputText value="#{cc.attrs.value}" escape="false"/>
</cc:implementation>
</ui:composition>
Don't forget to add the folowwing namespace in your xhtml pages where the components are used xmlns:field="http://java.sun.com/jsf/composite/components/myComponents in the ui:composition tag
Hope this helps...

Avoiding duplicate ids when reusing facelets compositions in the same naming container

I have a <ui:composition> that contains a few elements with explicit ids and some ajax events which reference these ids for partial processing/updating. I encapsulated this fragment of xhtml inside the composition simply so I could use it in a few different places without having to duplicate the code. However, when I use the composition (with <ui:include>) more than once inside a page, I get duplicate id exceptions. It seems JSF is not wrapping each composition inside its own naming container (like <ui:component> does).
Is there a simple way to wrap my composition inside its own naming container?
Or do I have to use a composite component every time I want to reuse xhtml fragments inside a common naming container?
Depending on the purpose of the <ui:include> template, you've several options:
Use <f:subview>. It creates another NamingContainer context (like as <h:form>, <h:dataTable>, and friends all do):
<f:subview id="top">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
...
<f:subview id="bottom">
<ui:include src="/WEB-INF/includes/some.xhtml" />
</f:subview>
The components definied in some.xhtml will end up getting respectively top: and bottom: prefix in their ID.
Turn it into a tagfile which requires an id attribute.
<my:some id="top" />
...
<my:some id="bottom" />
And use that ID to prefix the ID of the components in the composition.
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
...
<h:someComponent id="#{id}_some" />
<h:otherComponent id="#{id}_other" />
...
<ui:composition>
Turn it into a composite component. Composite components are inherently already a NamingContainer, so their id attribute is optional. Basically, replace
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets"
>
...
<ui:composition>
by
<ui:component
xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
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>
<!-- This is optional. -->
</cc:interface>
<cc:implementation>
...
<h:someComponent id="some" />
<h:otherComponent id="other" />
...
</cc:implementation>
<ui:component>
This way you can use it as follows:
<my:some id="top" />
...
<my:some id="bottom" />
The components definied in <cc:implementation> will end up getting respectively top: and bottom: prefix in their ID (note again, the composite component's id attribute is optional, JSF will otherwise autogenerate one).
See also:
When to use <ui:include>, tag files, composite components and/or custom components?
When you include more than once the same ui:composition the id are duplicated. The solution is to specifiy a particular ui:param within the ui:include.
Assuming you're including mycomposition.xhtml you can do something similar:
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="first"/>
</ui:include>
...
<ui:include src="mycomposition.xhtml">
<ui:param name="idPrefix" value="second"/>
</ui:include>
Then in the mycomposition.xhtml you should declare the ids as follows (for instance a h:outputText):
<h:outputText id="#{idPrefix}_text" value="My Awesome Text here"/>
Now you can reference the id in the rest of yout page as #{idPrefix}_text.

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.

Private/scoped variable in JSF2/Facelets <ui:component>?

I might not be thinking correctly in terms of visual components in JSF, but I guess that's part of my question. My question is around the seeming lack of scope around variables declared within JSF <ui:component> implementations.
So, say I have /resources/comp/myPanel.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<ui:component xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:cc="http://java.sun.com/jsf/composite">
<cc:interface>
</cc:interface>
<cc:implementation>
<f:loadBundle var="bundle" basename="panelOnly.bundle" />
<h:outputText value="#{bundle.myText}" />
</cc:implementation>
</ui:component>
And there is a resource bundle that gets loaded in that component, panelOnly/bundle.properties:
myText = This is a panel resource
And then I have a page that places the myPanel component, mainPage.xhtml:
<?xml version="1.0" encoding="UTF-8" ?>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:comp="http://java.sun.com/jsf/composite/comp">
<h:body>
<f:view>
<f:loadBundle basename="mainPage.bundle" var="bundle" />
<comp:myPanel />
<h:outputText value="#{bundle.myText}" />
</f:view>
</h:body>
</html>
and there is a resource bundle that gets loaded in the main page, mainPage/bundle.properties:
myText = This is a main page resource
Now, I would assume that my page should render as:
This is a panel resource
This is a main page resource
But, instead, I get:
This is a panel resource
This is a panel resource
And I assume that is because I clobbered what the "bundle" symbol refers to in my component so that when the mainPage.xhtml tries to resolve that value, it looks to the component's "bundle" object and not the original mainPage's.
My workaround to date has been to just use unique named variables within my components that would never clash with variables on my main pages. But I would prefer if there was a way to coax JSF to recognize anything declared in my component as locally scoped variables and not clobber the caller's symbols.
I think there are and other tags that one can use to make locally scoped variables under #{cc.attrs...}. If you could enumerate my local scoping options in your answer, that would be very helpful. I suspect my <f:loadBundle> is a special case, and maybe there isn't a workaround for that one as it was not designed with <ui:component> in mind.
Thanks!
P.S. I'm running Mojarra 2.1.1 (FCS 20110408)
(edited for formatting and copy and paste bugs 6/15/2011)
Unfortunately, that's how <f:loadBundle> works. It's an one-time setting for the entire view. And any subsequent <f:loadBundle> calls in the same view will just override the previous one.
Your best bet is to manage it by a backing component.
<cc:interface componentType="myPanel">
with
#FacesComponent(value="myPanel")
public class MyPanel extends UIComponentBase implements NamingContainer {
private ResourceBundle bundle;
public MyPanel() {
bundle = ResourceBundle.getBundle("panelOnly.bundle",
FacesContext.getCurrentInstance().getViewRoot().getLocale());
}
#Override
public String getFamily() {
return "javax.faces.NamingContainer";
}
public ResourceBundle getBundle() {
return bundle;
}
}
which can be used as
<cc:implementation>
<h:outputText value="#{cc.bundle.myText}" />
</cc:implementation>

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