JSF / Primefaces - ui: param in p: ajax element

I am writing an application in Java EE 6 and using Primefaces 3.4.1 for the user interface.

I have something like this.

genericPage.xhtml

<ui:composition template="mainApplicationTemplate.xhtml" [...]> <p:tabView id="tabView" dynamic="false"cache="false"> <p:tab id="tab1" title="Tab 1"> <h:form id="form1"> ... </h:form> </p:tab> <p:tab id="tab1" title="Tab 1"> <h:form id="form2"> ... </h:form> </p:tab> </p:tabView> <ui:composition > 

child1.xmtml

 <ui:composition template="genericPage.xhtml" ...> <ui:param name="actionBean" value="#{actionBeanA}"/> </ui:compisition> 

child2.xmtml

 <ui:composition template="genericPage.xhtml" ...> <ui:param name="actionBean" value="#{actionBeanB}"/> </ui:compisition> 

The idea is that child1.xhtml and child2.xhtml use the same jsf code, all of which are contained in the genericPage.xhtml file, but they have different bean backends (parameterized "actionBean")

So far it works very well. This gets complicated when I set the ui parameter inside the <p:ajax/> element.

From the bean backend, I need to programmatically update the active tab, leaving the other untouched. To do this, I need to keep the active tab in the bean action. When certain external events occur, the bean action updates the active tabs.

Please note that due to some other factors:

  • I cannot set dynamic="true" in tabView
  • I cannot have a global shape around a tabView and therefore cannot use the activeIndex property (which I do in another part of the application) to control the active tab.

What i want to do

To solve this problem, I want to use the tabChange event of the tabChange element:

 <p:tabView id="tabView" dynamic="false"cache="false"> <p:ajax event="tabChange" listener="#{actionBean.listen}" <p:tab id="tab1" title="Tab 1"> <h:form id="form1"> ... </h:form> </p:tab> <p:tab id="tab1" title="Tab 1"> <h:form id="form2"> ... </h:form> </p:tab> </p:tabView> 

action bean

 @Named @WindowScoped public class ActionBeanA implements Serializable{ public void listen(TabChangeEvent event){ ... } } 

What does not work

When I do this, I get an error

 Target Unreachable, identifier 'actionBean' resolved to null: javax.el.PropertyNotFoundException: Target Unreachable, identifier 'actionBean' resolved to null 

This, apparently, indicates that the <p:ajax> element did not pass the bean action and therefore does not know what the actionBean .

However, if I change the signature of a listener method like

 <p:ajax event="tabChange" listener="#{actionBean.listen(anything)}" 

and change the bean backend to something like:

 public void listen(TabChangeEvent event){ System.out.println(event.toString()); } 

By doing this, I do not get an invalid target error, but a null pointer exception in the listening method (because I did not assign the value "nothing"). This shows that in this case the <p:ajax/> elements know that actionBean is an actionBean and it is possible to call the method in the bean.

Questions

How could I get around this? I would like to be able to send a new active tab to my backend bean in the tab change event.

+4
source share
2 answers

I also had this problem and found a solution in the Primefaces problem tracker: Solution found in post # 20

To summarize, this is a known issue in Primefaces. Half-fix found in version 3.4.2 and requires some code changes. At the moment you have:

 public void listen(TabChangeEvent event){ System.out.println(event.toString()); } 

What does not work. You must change your code to:

 public void listen(AjaxBehaviorEvent event){ System.out.println(event.toString()); } 

And if you need to use certain TabChangeEvent methods, then you need to cast: (TabChangeEvent)event .

It has the status recorded in the tracker problem, so this may be required as a permanent solution.

+5
source

There is a difference between processing a value expression and a method. For the latter, you need to have an option available a little later - in the context of Facelet.

To include a parameter value in a facelet context, you just need to place the parameter value definition inside the <f:metadata> .

Also note that the <f:metadata> should always be a direct child of the <f:view> , so I would do something like this:

template.xhtml

 <f:view ....> <ui:insert name="metadata"/> .... </f:view> 

childPage.xhtml

 <ui:composition template="/WEB-INF/template.xhtml"> <ui:define name="metadata"> <f:metadata> <ui:param name="actionBean" value="#{actionBeanA}" </f:metadata> </ui:define> </ui:composition> 

After that, you can use the listener attribute in template.xhtml original mode without workarounds, and your method will always be called with the corresponding parameter of the event type.

0
source

All Articles