Nested JSF composite components not fully compatible with Primefaces - jsf

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.

Related

h:outputStylesheet inside ui:repeat

I'm trying to use to output a stylesheet link for every element of an ArrayList. This code produces no result:
<ui:repeat value="#{includer.css}" var="ss">
<h:outputStylesheet name="#{ss}" library="css" />
</ui:repeat>
However, if i change the Strings in the ArrayList to be full paths and replace h:outputStylesheet with plain html like :
<ui:repeat value="#{includer.css}" var="ss">
<link type="text/css" rel="stylesheet" href="${ss}" />
</ui:repeat>
then it works as expected. The problem with this is i have some EL expressions in some css files and it seems they are not being evaluated, I assume because i'm referencing them directly like that.
Thanks for any insight.
The <h:outputStylesheet> (and <h:outputScript>) needs to be present during view build time in order to let the JSF resource management to properly pickup them. The <ui:repeat>, however, runs during view render time only, it would be too late for JSF to perform relocation actions (moving to bottom of head or body, etc).
Replace it by <c:forEach>.
<c:forEach items="#{includer.css}" var="ss">
<h:outputStylesheet name="#{ss}" library="css" />
</c:forEach>
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, a library name of css is wrong. Carefully read What is the JSF resource library for and how should it be used?

JSF page lost style after partial update

I have some troubles with partial update of jsf 2.0 page.
I have dropdown menu with few choices. Depending on choice I show different page. When I load page first time it shows css and javascript works fine. When I change another option in dropdown menu this part of page which has been re rendered appearing without css and javascript on it doesn't work.
This is example of page itself which I using, template.xhtm and bean are pretty generic therefor I didn't include it.
<ui:composition template="/template.xhtml"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:t="http://myfaces.apache.org/tomahawk"
xmlns:h="http://java.sun.com/jsf/html">
<ui:define name="body">
<h:form>
<h:selectOneMenu value="#{bean.answer}">
<f:selectItems value="#{bean.answers}" />
<f:ajax event="change" render="includeContainer #All" />
</h:selectOneMenu>
</h:form>
<h:panelGroup id="includeContainer">
<h:panelGroup library="primefaces" name="jquery/jquery.js"
rendered="#{bean.answer == 'yes'}">
<ui:include src="answer_yes.xhtml"></ui:include>
</h:panelGroup>
<h:panelGroup rendered="#{bean.asnwer == 'no'}">
<ui:include src="answer_no.xhtml"></ui:include>
</h:panelGroup>
</h:panelGroup>
</ui:define>
</ui:composition>
One important remark regarding template that I use this statement to include css, it's located on remote server and I can't download and place it locally, it's company's policy.
<link href="http://server.com/resources/w3.css" rel="stylesheet" title="w3" type="text/css" />
Thank you in advance for your help.
You can put rendered panel group inside an <h:form id="toberendred"> and re-render this form instead of h:panelGroup.
For proper (JSF way) loading your css file from remote server you can use Omnifaces CDNResourceHandler
In addition you got some serious issues in your code:
Why use #all (fix to lowercase) with additional (includeContainer) selector? , do view source and see that you can't render <ui:include in view source you will see content of both yes and no xhtmls + <h:panelGroup got no attributes library and name...

Unable to understand <h:head> behaviour

I have a template composition Button.xhtml which contains a <p:commandLink>:
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:p="http://primefaces.org/ui">
<p:commandLink value="View" action="#{printClass.printPdf}"/>
</ui:composition>
The link's purpose is to generate PDF.
I have a template client defaultPage.xhtml where the Button.xhtml is been included.
<ui:composition template="../../WebPages/MasterPage/Template.xhtml">
<ui:define name="MainContent">
<ui:include src="../../WebPages/Facelets/Button.xhtml"/>
</ui:define>
</ui:composition>
The last one is Template.xhtml which inserts the MainContent template definition inside a <h:form>.
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core">
<h:body>
<h:form>
<ui:insert name="MainContent" />
</h:form>
</h:body>
</html>
When I place <h:head></h:head> in Template.xhtml, then the <p:commandLink> in Button.xhtml stops working, but CSS of page works perfect. When I remove the <h:head></h:head> or replace it by <head></head> then the <p:commandLink> starts working, but CSS stops working.
How is this caused and how can I solve it?
The <h:head> will auto-include all necessary JavaScript files for ajax behavior and CSS files for layout. When you remove it, then CSS will not be auto-included and ajax behavior will not be enabled. The <p:commandLink> would then act like as a plain vanilla link.
The <h:head> is absolutely necessary for proper functioning of JSF and PrimeFaces components and applying of the PrimeFaces look'n'feel. So you should not remove or replace it.
Let's concentrate on the problem of the failing <p:commandLink>. There are relatively a lot of possible causes, which are all mentioned in this answer: commandButton/commandLink/ajax action/listener method not invoked or input value not updated
You didn't show a fullworthy SSCCE, so it's impossible to copy'n'paste'n'run your code to see the problem ourselves (work on that as well in your future questions). So, I'll just mention the most probable cause for this problem based on the symptoms: you're nesting <h:form> components in each other. Placing the <h:form> in the master template is also a design smell. You should rather place it in the template client. Als note that the <p:dialog> should have its own form but that the <p:dialog> should by itself not be nested in another form.
Update: based on the comments, you're trying to return a whole PDF file as a response to an ajax request. This will indeed not work. The ajax engine expects a XML response with information about changes in the HTML DOM tree. A PDF file isn't valid information. Also, JavaScript has for obvious security reasons no facilities to programmatically trigger a Save As dialogue whereby possibly arbitrary content is provided.
You can't download files by ajax. You have to turn off ajax. In case of <p:commandLink> there are basically 2 solutions:
Use ajax="false".
<p:commandLink ... ajax="false" />
Just use <h:commandLink> instead.
<h:commandLink ... />
In Button.xhtml where you placed
<h:commandLink value="View" action="#{printClass.printPdf}"/>
You need to disable the ajax.So your new code should be like
<h:commandLink value="View" action="#{printClass.printPdf}">
<f:ajax disabled="true"></f:ajax>
</h:commandLink>

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?

JSF2.0 Composite Component ID generation

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();
});

Resources