Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve value of a ui:param in the backing bean

I'm passing a parameter p1 to another page page.xhtml:

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

Is this possible to evaluate #{p1} inside @PostConstruct method of the backing bean of page.xhtml? Using the following piece of code, #{p1} cannot resolve:

FacesContext currentInstance = FacesContext.getCurrentInstance();
currentInstance.getApplication().evaluateExpressionGet(currentInstance, "#{p1}", String.class);

Why do I need this?

I'm using an xhtml file (say component.xhtml) as a custom UI component. This file has a backing bean from which I should get component data. Since I'm including this xhtml file twice or more in my main JSF page, I want to pass different objects to each of component.xhtml so that my component work with my custom data each time included.

like image 558
Mohsen Avatar asked Jan 22 '13 13:01

Mohsen


2 Answers

In Mojarra, you can get it as an attribute of the FaceletContext. You can get it in the @PostConstruct of a managed bean which is guaranteed to be referenced/constructed for the first time in the included page (and thus not in the parent page before the <ui:param> is declared in the component tree).

FaceletContext faceletContext = (FaceletContext) FacesContext.getCurrentInstance().getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
Object p1 = faceletContext.getAttribute("p1");

In MyFaces, the whole FaceletContext isn't available in managed beans as it's discarded by end of view build time and this construct would then not work. To be JSF implementation independent, you might want to consider to set it via <c:set scope="request"> instead. It's then available as a request attribute.

As to the concrete functional requirement, consider creating a comoposite component with a backing component. For some examples, see our composite component wiki page and this blog about using multiple input components in a composite component. See also When to use <ui:include>, tag files, composite components and/or custom components?

like image 87
BalusC Avatar answered Nov 18 '22 23:11

BalusC


The param is not available in the @PostConstruct method; you can use the preRenderComponent event to initialize the parameters inside your backing bean; just put it after the ui:composition of the included page, it will be executed before the rendering of the included page itself.

Following the OP example of a passing a p1 parameter to a page.xhtml template

the main page:

<ui:include src="page.xhtml">
    <ui:param name="p1" value="#{someObject}"/>
</ui:include>

page.xhtml:

<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    ...>

<ui:composition>
    <f:event listener="#{backingBean.init(p1)}" type="preRenderComponent"/>
        ...

</ui:composition>

</html>

BackingBean.java:

@ViewScoped
 public class BackingBean{

     private Object p1;
     public void init(Object value){        
     this.p1=p1;
    }

    ...
 }

the event is fired before the render of the ui:composition tag, that is before the render of page.xhtml

like image 25
Bruno F Avatar answered Nov 18 '22 21:11

Bruno F