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>
tagHtmlBody
: this is h:body
apparently. Ask for getChildren
to get <h:outputText>
UIInstructions
: renders the </html>
closing tagadd 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);
}
}