h:outputText to conditionally render groups of JSF elements no longer working in JSF 2? - jsf

I have some code that uses <h:outputText> to conditionally render groups of JSF elements. Examples:
<h:outputText rendered="#{authorization.admin}">
<h:outputText value="#{msgs.someinfo}" />
<h:inputSecret value="#{usermanager.password}" />
</h:outputText>
<h:outputText rendered="#{contactmanager.editAction}">
<li>
<label for="name"><h:outputText value="#{msgs.nameinfo}" /></label>
<h:inputText id="name" value="#{contactmanager.name}" />
<h:messages for="name" />
</li>
</h:outputText>
The code is on glassfish 2.1.1 which has the MANIFEST.MF in jsf-impl.jar looking like this (I'm not sure whether it actually uses this jar or some other one for JSF):
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.5.0_19-b02 (Sun Microsystems Inc.)
Specification-Title: JavaServer Faces
Specification-Version: 1.2MR2
Implementation-Title: Mojarra
Implementation-Version: 1.2_13-b01-FCS
Implementation-Vendor: Sun Microsystems, Inc.
Implementation-Vendor-Id: com.sun
Extension-Name: com.sun.faces
I'm trying to move to glassfish 4 which has some version of JSF 2 or higher.
All the hundreds of instances of this construct worked on the old glassfish, but they no longer work on the new one - they are replaced with nothing, regardless of what the rendered attribute evaluates to. Why?

Indeed, since JSF 2.0, children of UIInput and UIOutput are by default not anymore rendered. This is the consequence of fixes for issue 1154. In Mojarra 2.x, you can still turn it back on via a web.xml context parameter:
<context-param>
<param-name>com.sun.faces.allowTextChildren</param-name>
<param-name>true</param-name>
</context-param>
See also the Mojarra 2.0.0 release notes.
It's however more recommended to instead use <h:panelGroup> or <ui:fragment> for conditional rendering of blocks as the <h:outputText> is just the Wrong Toolâ„¢ for the job.

Related

Do I have to pass ui:param in template if I am using ui:composite and ui:insert, ui:include?

I have one page main.xhtml, which contains ui:composition. This composition uses template1.xhtml file. template1.xhtml file contains ui:insert, ui:include tag which are pointing to template2.xhtml file. Now, I want to use parameters that are passed from ui:composition inside template2.xhtml.
main.xhtml
<ui:composition template="template1.xhtml">
<ui:param name="a1" value="val1"/>
</ui:composition>
template1.xhtml
<ui:insert name="header">
<ui:include src="template2.xhtml">
</ui:insert>
template2.xhtml
<h:panelGroup rendered="#{not empty a1}" layout="block">
<h4>#{a1}</h4>
</h:panelGroup>
My question is can I directly access parameter named a1 or I had to again pass ui:param in ui:include?
Depends on Facelets version and JSF impl/version.
In original Facelets 1.x, any <ui:param> in parent composition is inherited into all <ui:include> children.
<ui:include src="template2.xhtml" />
In Facelets 2.x as integrated in JSF 2.x, any <ui:param> of a parent composition which ought to be reused in an <ui:include> (or <ui:decorate>) must be explicitly passed through.
<ui:include src="template2.xhtml">
<ui:param name="a1" value="#{a1}" />
</ui:include>
At least, that's the case when you're using Mojarra 2.x. In MyFaces 2.0 / 2.1, however, it was not necessary as the original Facelets 1.x behavior unintentionally slipped into MyFaces 2.0 / 2.1.
<ui:include src="template2.xhtml" />
They have fixed it in MyFaces 2.2, so you need to explicitly pass them through.
<ui:include src="template2.xhtml">
<ui:param name="a1" value="#{a1}" />
</ui:include>
In case you're using MyFaces 2.2 or newer, and want to retain the original Facelets 1.x behavior, then you can add the following context param to web.xml:
<context-param>
<param-name>org.apache.myfaces.STRICT_JSF_2_FACELETS_COMPATIBILITY</param-name>
<param-value>true</param-value>
</context-param>
<ui:include src="template2.xhtml" />
No such context param exist for Mojarra, so this should not be relied upon in case you want to have your code to work the same across all JSF implementations.

render="#form" with Omnifaces 2.0 and Richfaces 4.5 not working

We're using a <a4j:commandLink ... /> with an action and render="#form". Since we've upgraded to Omnifaces 2.0 the action won't be invoked unless we replace #form with #this or an explicit id. The bean providing the action method is annotated with #javax.faces.view.ViewScoped.
Before with Omnifaces 1.8.1 it has worked well.
(We're using Java 8, JSF 2.2.6, Richfaces 4.5 and Wildfly 8.)
<a4j:commandLink id="#{cc.attrs.buttonId}"
action="#{cc.attrs.action}"
oncomplete="#{cc.attrs.oncomplete}"
onbegin="#{cc.attrs.onbegin}"
render="contentForm:contentSaveHandler contentToolbar #form"
execute="#this">
<h:outputText value="Test" />
</a4j:commandLink>
If I change #form to #this it works.

How to add tooltip to f:selectItems

For example the f:selectItems component doesn't support the title attribute in some versions of JSF.
Would it be possible to replace JSF Components by their plain HTML counterparts using JSFC and do something like this?
<select jsfc="h:selectOneMenu" value="#{cc.data}">
<option jsfc="f:selectItems" value="${cc.listItems}" var="item" title="#{item.tooltip}"></option>
</select>
instead of
<h:selectOneMenu value="#{cc.data}">
<f:selectItems value="#{cc.listItems}" />
</h:selectOneMenu>
Doing exactly so, replacing the latter by the above, I'm getting "<f:converter> Parent not an instance of ValueHolder: javax.faces.component.html.HtmlPanelGroup" Facelet TagExceptions
Would it be possible to replace JSF Components by their plain HTML counterparts using JSFC and do something like this
Nope. Ultimately, such a HTML element with jsfc attribute will be turned into a true JSF component in the JSF component tree and only the attributes supported by the component in question would be parsed and set as component attribute. The title attribute isn't among the supported attributes of UISelectItem component. I'm not sure what exactly you mean with "some versions of JSF". The standard JSF API already doesn't support it in first place. JSF spec issue 529 describes this shortcoming and is currently still open.
If you're using JSF 2.2, make use of passthrough attributes. You only need to replace <f:selectItems> by <c:forEach><f:selectItem>, see also Using f:selectItems var in passtrough attribute
<... xmlns:a="http://xmlns.jcp.org/jsf/passthrough">
<c:forEach value="#{bean.items}" var="item">
<f:selectItem itemValue="#{item}" a:title="#{item.tooltip}" />
</c:forEach>
Based on your question history you seem to be not using JSF 2.2 yet. If you can't upgrade, you basically need a custom renderer for <h:selectOneMenu>.
While creating the custom renderer, you could make use of the unused(!) description property of the UISelectItem class. I've answered this before on a similar question targeted at <p:selectManyCheckbox>: Primefaces tooltip for p:selectManyCheckbox or other p:selectMany*/One*.
<f:selectItems ... var="item" itemDescription="#{item.tooltip}" />
Noted should be that creating the custom renderer for <h:selectOneMenu> is a pain, particularly if you intend to be JSF implementation independent. Theoretically, a custom ResponseWriter should be able to catch this, but unfortunately, the <h:selectOneMenu> only passes itself when writing <option>, instead of the UISelectItem in question.
In my case (JSF 2.2 / Mojarra 2.2.14), itemDescription worked out of the box. I.e:
<c:forEach items="#{bean.items}" var="item">
<f:selectItem itemValue="#{item}" itemLabel="#{item}" itemDescription="#{item.tooltip}" />
</c:forEach>

UTF-8 in PrimeFaces 3.x

I have a very simple application,there is an inputtext in my index page and a button to go to page2.xhtml.
<h:body>
<h:form>
<h:inputText value="#{mainBean.testValue}"/>
<p:commandButton update="myoutput" value="ajax call" ajax="false"/>
<p:separator />
<h:commandButton action="#{mainBean.gotoPageTwo}" value="goto Page2"/>
<br/>
<h:outputText value="#{mainBean.testValue}" id="myoutput"/>
</h:form>
</h:body>
</html>
I tested this application with PrimeFaces 2.2.1 and there was no problem.
but after submit each of the above button, my UTF-8 characters will destroy.
I tested filter but it don't work.
Is it a bug in PrimeFaces 3.x?
Can any body solve this problem?
The web.xml example of the answer you found at PrimeFaces forum is incomplete. The <filter-mapping> is missing. Without that, the filter won't even run at all. Add it accordingly
<filter-mapping>
<filter-name>Character Encoding Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
When you're already on Servlet 3.0 (Tomcat 7, Glassfish 3, etc), an alternative is to use just the #WebFilter annotation on the class. Don't forget to remove the filter entry from web.xml.
#WebFilter("/*")
For a background explanation of the cause of this character encoding problem during PrimeFaces 2.x-3.x upgrade, see also Unicode input retrieved via PrimeFaces input components become corrupted

JSF tag not found

I use JSF-facelets.jar 1.1.14 (I downloaded it here) and tomcat 6.0
Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.0
Created-By: 1.5.0_12-b04 (Sun Microsystems Inc.)
Implementation-Version: 1.1.14
If I understand well, JSF-facelets.jar = JSF + JSTL + Facelets (???)
My problem is when I use "fmt" fonction.
This code...
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:fmt="http://java.sun.com/jstl/fmt">
<h:outputLabel value="hello" />
<fmt:formatDate value="${myBean.date}" pattern="dd/MM/yyyy"/>
</html>
...generate this HTML code:
<html>
<p>hello</p>
<fmt:formatDate value="${myBean.date}" pattern="dd/MM/yyyy"/>
</html>
Why "fmt:formatDate" is not change into HTML code ???
The correct way to achieve this in JSF is to use converters. Use the <h:outputText> tag like so:
<h:outputText value="#{myBean.date}">
<f:convertDateTime pattern="dd/MM/yyyy" />
</h:outputText>
You'll find that not all JSTL tags are supported in JSF. Facelets does provide limited support for the core tag library (forEach, etc) but they might not work the way you expect them to. This article provides a good summary: http://drewdev.blogspot.com/2008/03/build-time-vs-render-time.html
that's a jstl tag. it doesn't need to be translated. it's compiled from a jsp into a servlet.
what did you expect it to be "translated" into?

Resources