h:outputStylesheet inside ui:repeat - jsf

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?

Related

Conditional include with empty value in JSF

I hope that I understood JSF correct and this all makes sense. I try to do some kind of simple templating within a page by using (conditional) includes.
The panel is updated by a selection.
<p:outputPanel id="panel">
<h:panelGroup rendered="#{not empty someBean.selectedObject}">
<ui:include src="WEB-INF/pages/#{someBean.selectedObject.pageName}.xhtml" />
</h:panelGroup>
</p:outputPanel>
If I am right the ui:include got processed in some kind of view preparation phase and the rendered attribute just before the page gets rendered. As a result I get a FileNotFoundException because it tries to load WEB-INF/pages/.xhtml. This makes quite some sense to me, but how to solve this problem without a messy hackaround like creating an empty page as a prefix for the filename (page.xhtml) and prefix every page that should be actually rendered with this string (pageSamplePage.xhtml)?
You need to conditionally build the <ui:include> instead of conditionally render it. Use <c:if> instead of rendered.
<p:outputPanel id="panel">
<c:if test="#{not empty someBean.selectedObject}">
<ui:include src="WEB-INF/pages/#{someBean.selectedObject.pageName}.xhtml" />
</c:if>
</p:outputPanel>
Otherwise, the <ui:include> still ends up in the component tree.
See also:
JSTL in JSF2 Facelets... makes sense?
Unrelated to the concrete problem, even when you intend to conditionally render parts of the view, you'd better use <ui:fragment> instead of <h:panelGroup> as it has less overhead.
Prevent usage of <c:if>, as it can break some of the standard JSF components.
We observed that its usage caused duplication of a child within UI:Panel as a side-effect, and it took a while to identify this as the root-cause.

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.

Template-based facelet tag library

I want to create a facelet component which is backed by template.
Something like that:
<h:panelGroup rendered="#{myBean.isStepActive('step0')}">
<composition template="wizard-step.jspx">
<ui:define name="title">Step One</ui:define>
<ui:define name="text"><p>This describes the step</p></ui:define>
</composition>
</h:panelGroup>
<h:panelGroup rendered="#{myBean.isStepActive('step1')}">
<composition template="wizard-step">
<ui:define name="title">Step Two</ui:define>
(...)
Is seems not to work as the content of wizard-step.jspx is put on any page no matter what renders returns (it seems like the ui: tags are evaluated before all other tags.
Is there a way to accomplish what I want?
A normal custom tag is not powerful enough in my case because it only supports xml attributes but no child elements.
Ok, I found the solution and it's pretty easy.
Just use a normal taglib and use < ui:insert> and < ui:define> like that:
<my:wizardStep>
<ui:insert name="title"><h2>The header comes here</h2>/ui:insert>
</<my:wizardStep>
And in the tag definition:
<ui:composition>
<ui:insert name="title" />
(...)

TinyMCE .js files not found when using JSF h:outputScript

I have a JSF 2.0 Webapplication into which I d'like to include TinyMCE 3.5.
The way I included it is like below:
<composite:implementation>
<h:outputScript name="tiny_mce/tiny_mce.js"/>
<h:outputScript name="js/tinymce_init.js"/>
<h:inputTextarea rows="5" cols="80" styleClass="tinymce" value="#{cc.attrs.value}"/>
</composite:implementation>
Now everything works fine. The only problem I have is that "tiny_mce.js" has some references to other js files in the tiny_mce folder. These references return a 404 error, because they have no .xhtml ending.
Example: tiny_mce.js references en.js. Its trying to load it from "http://localhost:8080/briefe/javax.faces.resource/js/tiny_mce/langs/en.js". If I enter this URL into the Browser I get a 404. If I add .xhtml in the end ("http://localhost:8080/briefe/javax.faces.resource/js/tiny_mce/langs/en.js.xhtml") everything works great.
So I d like to ask you, if there is a way I can add xhtml as default ending for .js files or if there is a way to make .js files accessible.
The <h:outputScript> will generate a JSF resource URL which is handled by ResourceHandler which in turn allows modularization and versioning without the need to ever change the <h:outputScript name>. When the FacesServlet is mapped on *.xhtml, the resource URL will look like this
/contextname/javax.faces.resource/filename.js.xhtml
The TinyMCE scripts are apparently auto-including some other scripts based on the script's own URL and not taking the .xhtml suffix into account.
/contextname/javax.faces.resource/otherfile.js
This will then indeed result in 404s. When you're using a prefix mapping for the FacesServlet like /faces/*, then this problem will not occur.
One solution is to hardcode the <script> with the desired URL yourself. The right substitute would then be
<script type="text/javascript" src="#{request.contextPath}/resources/tiny_mce/tiny_mce.js"/>
<script type="text/javascript" src="#{request.contextPath}/resources/js/tinymce_init.js"/>
The only disadvantage is, when you're using multiple composite components in a single view, then you'd end up with multiple <script> entries in the body instead of only one as taken care by <h:outputScript>. This may end up in JavaScript conflicts/errors. If you encounter this problem, I'd consider to hack/fix the TinyMCE JavaScript file accordingly that it adds the .xhtml suffix to the URL, so that you can keep using <h:outputScript>. Or, you can of course use an existing and ready-to-use JSF rich text editor component such as PrimeFaces <p:textEditor>, so that you don't need to worry about this all.
You can also test this instead of <h:outputScript...>
this:
<composite:implementation>
<script language="text/javascript" src="tiny_mce/tiny_mce.js" />
<script language="text/javascript" src="js/tinymce_init.js" />
<h:inputTextarea rows="5" cols="80" styleClass="tinymce" value="#{cc.attrs.value}"/>
</composite:implementation>
or something like this:
<script language="text/javascript" src="tiny_mce/tiny_mce.js" />
<script language="text/javascript" src="js/tinymce_init.js" />
<composite:implementation>
<h:inputTextarea rows="5" cols="80" styleClass="tinymce" value="#{cc.attrs.value}"/>
</composite:implementation>
I've just came across this problem and the simplest solution is that you add missing files the same way you added for tiny_mce.js
<!-- TinyMCE -->
<h:outputScript library="libs" name="js/tinymce/4.1.10/tinymce.min.js"></h:outputScript>
<!-- TinyMCE theme -->
<h:outputScript library="libs" name="js/tinymce/4.1.10/themes/modern/theme.min.js"></h:outputScript>
<!-- TinyMCE plugins -->
<h:outputScript library="libs" name="js/tinymce/4.1.10/plugins/advlist/plugin.min.js"></h:outputScript>
<h:outputScript library="libs" name="js/tinymce/4.1.10/plugins/autolink/plugin.min.js"></h:outputScript>
<h:outputScript library="libs" name="js/tinymce/4.1.10/plugins/lists/plugin.min.js"></h:outputScript>
<h:outputScript library="libs" name="js/tinymce/4.1.10/plugins/charmap/plugin.min.js"></h:outputScript>

AutoSuggest running problem

This XML file does not appear to have any style information associated with it. The document tree is shown below.
<html xmlns="http://www.w3c.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.prime.com.tr/ui">
<h:head>
<link type="text/css" rel="stylesheet" href="themes/bluesky/skin.css"/>
</h:head>
<h:body>
<center>
<p:panel header="Login Form" style="width: 350;">
<h:form>
<h:panelGrid columns="2" cellpadding="2">
<h:outputLabel for="#{UserManagedBean.username}" value="UserName"/>
<h:inputText value="#{UserManagedBean.username}" label="UserName"/>
<h:outputLabel for="#{UserManagedBean.password}" value="Password"/>
<h:inputSecret value="#{UserManagedBean.password}"/>
<h:commandButton type="submit" value="Login" action="#{UserManagedBean.login}"/>
</h:panelGrid>
</h:form>
</p:panel>
<div>
<h:messages/>
</div>
</center>
</h:body>
</html>
What could be the possible problem here? I really don't know.
This XML file does not appear to have any style information associated with it. The document tree is shown below.
This is a typical MSIE warning message whenever you request a X(HT)ML file which does not have a XSL stylesheet (which is basically like CSS for HTML).
That you're getting this on a Facelet page can only mean that the request URL did not match the URL pattern of the FacesServlet as definited in your webapp's web.xml. In other words, the FacesServlet has never got any chance to run, parse that Facelet file and do all the JSF works to generate a bunch of HTML so that the webbrowser has something sensible to work with.
There are 2 solutions for this problem:
Fix your request URL (the one in browser address bar) to match the URL pattern of the FacesServlet in web.xml. If it is for example <url-pattern>*.jsf</url-pattern>, then you need to replace .xhtml extension in URL by .jsf.
Change the URL pattern of your FacesServlet to <url-pattern>*.xhtml</url-pattern>. This way you do not need to worry about accidently seeing XHTML source anymore.
Please note that this all has nothing to do with "autosuggest problem". Work yourself through some basic JSF tutorials first. Our JSF wiki page has some good links.
Oh, before I forgot, the <center> element is deprecated since HTML4 in 1998. Do not use it. Use CSS margin: 0 auto;. Try to avoid reading tutorials/books older than 2 years.

Resources