Passing data to a JSF facelet - jsf

On the 1st page that is displayed in my JSF application, I want to display data from a database in the form of a table. I have a ManagedBean called a ProductList which has an ArrayList of Product Objects, and I want to put all the Products in a table. I am using the jstl c:forEach tags, but for some reason I get a compile error:
Fatal Error: The prefix "c" for element "c:forEach" is not bound.
Am I using the forEach tag correctly?
<c:forEach items="#{productList.allProducts}" var="product">
</c:forEach>
Here are the namespace tags:
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">

You must define all the namespaces(the h:, f:prefixes of your xml tags) that you use in the page.
The proper definition for xmlns:c is xmlns:c="http://java.sun.com/jsp/jstl/core"
You can have a longer example here: <c:if test> seems to always evaluate true in JSF2 Facelets

Related

Best way to extend a particular section in JSF multilevel template

I have a multi level JSF template, say layout.xhtml, which extends from number of template which is depicted below.
layout.xhtml -> level3.xhtml -> level2.xhtml ->level1.xhtml
How to extend level1.xhtml and add one extra facelets ( I want 2 facelets overall) say customer-data.xhtml and supplier-data.xhtml ) inherited from level1.xhtml in place of navigation-module, and have all the facelets of layout.xhtml too?
Below is my template/level1.xhtml
<ui:composition
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:insert name="navigation-module" />
<ui:insert name="time-module" />
</ui:composition>
I want to get the common template i.e. layout.xhtml I am not getting how to do this.
I believe that you want to add two pages for the navigation-module. Its very easy, just do the below
<ui:composition
template=template/layout.xhtml
xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<ui:define name="navigation-module">
<ui:insert name="WEB-INF/customer-data.xhtml" />
<ui:insert name="WEB-INF/supplier-data.xhtml" />
</ui:define>
As long as you provide the correct ui:insert name i.e. in your case it is navigation-module, and in your ui:define you are telling to JSF, please insert these pages in place of navigation-module. Two keypoints to note here are
Make sure you mention your template name i.e. you can see immediate after ui:composition tag, i.e. template/layout.xhtml ( the reason being you want all the template features)
Use the exact name you want to override in ui:define i.e. in your case it is navigation-module
I hope I am clear to you. Incase you need any further clarification please feel free to drop a comment.

JSF - how to add child to h:head or to h:body with managed bean

I am trying to test my managed bean to modify web page dynamically (programmatically); Most of jsf examples show how to use binding to modify ui but what about the rest of the web page? The samples are showing how to get to the UIViewRoot which is usually located in h:body block but what about the h:body itself or the h:head?
So my question is... Is there a way using FacesContext to get h:body or h:head as parent components and add children to them right with managed bean or please advise of how to get alike effect using other ways?
Thanks
UIViewRoot is represented by <f:view> tag. If you don't define it explicitly in your JSF page, then it is added implicitly.
UIViewRoot which is usually located in h:body block
No, it is not inside the body, but by default surrounding the body and head. Like this:
<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">
<f:view> <!-- No need to define. Added implicitly here in ComponentTree -->
<h:head>
<meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
</h:head>
<h:body>
<h:outputText value="#{hello.message}"/>
</h:body>
</f:view>
</html>
So if you obtain the UIViewRoot using FacesContext.getCurrentInstance().getViewRoot() and ask for its children (.getChildren()), you will get a list of 4 elements:
UIInstructions: renders <html>opening tag
UIOutput: this is the <h:head>. Ask for getChildren again to obtain a UIOutput for the <meta> tag
HtmlBody: this is h:body apparently. Ask for getChildren to get <h:outputText>
UIInstructions: renders the </html> closing tag
add children to them right with managed bean
Yes, in general you can use your ManagedBeans to manipulate the UIComponentTree (e.g. add item, then reload the page to show it). However, consider the JSF lifecycle and processing order (you e.g. cannot add a child as first element to the body during render-phase, cause items were already processed).
Sample to add new element to body:
List<UIComponent> viewRootChildren = FacesContext.getCurrentInstance().getViewRoot().getChildren();
for(UIComponent child : viewRootChildren){
if( child instanceof HtmlBody ){
HtmlOutputText newText = new HtmlOutputText();
newText.setValue("added dynamically");
child.add(newText);
}
}
You can display/hide your JSF components using the rendered attribute.
Below is a sample -
<h:outputText value="Result = #{calculator.result}" rendered="#{calculator.result != null}"/>
Here, this element will be displayed in UI only if calculator.result is not null where calculator is the name of your managedBean and result is a variable inside that bean. You can change value of this variable in pre-render event or in AJAX call or in other events.
For more than one element, you can use <h:panelGroup> with rendered attribute.

How to render XML from a JSF 2.0 page

I'd like to build VXML using JSF2.0 but I didn't find any supporting tags. What we've proposed is writing xhtml pages with vxml data (having references to backing bean where ever value needs to get replaced) by having content type as 'text/xml' so client can read the xml directly.
<html 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">
<f:view contentType="text/xml">
<vxml>
<log>Caught the event </log>
<prompt bargein="true">
<audio src="built-in: #{myBackingBean.prompt}" />
</prompt>
</vxml>
</f:view>
</html>
But when ever I try to launch above xhtml page in a browser or using a REST webservice client -
1) I'm not seeing xml returned. But just Caught the event as output in browser. REST client is not seeing any output.
2) myBackingBean.prompt value is not getting replaced
Can any one suggest please? We do not want to use plain old servlets to construct the xml. We'd like to write XML manually but need values to be replaced from backing bean.

facelets ui:fragment ignores rendered attribute

i'm having a very strange behaviour with this piece of code:
<ui:fragment rendered="#{price.guestIdTrue}">
<b>PRICE_GUEST_ID_TRUE : #{price.guestIdTrue}</b>
<h:outputText>#{Global.guestTypeMap[price.guestId]} #{price.guestIndex}</h:outputText>
</ui:fragment>
Even when the rendered condition is false, the
PRICE_GUEST_ID_TRUE : false 1
1 is the #{price.guestIndex}
The ui namespace is correctly defined, and it works on others facelets.
<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:p="http://primefaces.org/ui"
xmlns:t="http://myfaces.apache.org/tomahawk">
Any Ideas of what happens.
Thanks in advance.
You seem to be using <ui:fragment> inside an iterating tag/component where the #{price} is actually the currently iterated variable, such as the JSTL <c:forEach> tag, or the JSF <h:dataTable> or <ui:repeat> component while using an early version of Mojarra. In those situations, the #{price} is not available in EL scope at the point it's been evaluated.
You need the <h:panelGroup rendered> instead or to upgrade the Mojarra version to the latest.

Use c:set to set a non-string value

Whenever doing <c:set var="name" value="1"/>, #{name} is always a String as evidenced by #{name.class}.
Is there any way to in a JSF/Facelets context to set a scoped attribute that is an Integer or Long literal value?
EL has Automatic Type Conversion. This article has some good information. However, the short of it is that you shouldn't care. You should be able to do things like the following as long as param.month is, in fact, an Integer.
<c:set var="myInteger" value="${param.month}"/>
<p>
The value of myInteger is:<c:out value="${myInteger}"/>
Perform a multiplication operation to show that the type is correct:
<c:out value="${myInteger *2}"/>
On JSF xhtml page, I use technics to reduce number of characters to type !
<!DOCTYPE html>
<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:p="http://primefaces.org/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:c="http://java.sun.com/jsp/jstl/core"
>
<!-- JSF ViewController of this page -->
<c:set var="vC" value="#{optionsViewController}"/>
...
<h:outputText
value="#{vC.txtOriginator.value}"
rendered="#{vC.txtOriginator.protected}"
/>
instead of
<h:outputText
value="#{optionsViewController.txtOriginator.value}"
rendered="#{optionsViewController.txtOriginator.protected}"
/>
Instead of typing optionsViewController more than 100 types, I write define only vC JSTL variable one time at begin of my xhtml file and use it each time I use optionsViewController.
OTHER advantages:
The xhtml code is more short and more readable.
When I copy some lines of code using Paste/Copy between distinct
xhtml pages, vC variable must not be replaced !

Resources