Board index JavaServer Faces General PF 3.0RC1-SNAPSHOT TabView "tabChange" listener issue

PF 3.0RC1-SNAPSHOT TabView "tabChange" listener issue

Components, Ajax Framework, Utilities and More.


Posts: 16
We have a complex PrimeFaces application with many tabs. Each tab is a separate page. And application needs to load appropriate page when some tab is selected.

To implement this we have done following:
1. Defined tab view with empty tab.
2. On tab change we check which tab is currently selected and depending on this define which
3. Updating with ajax output panel which includes some page
<p:outputPanel id="mainAppFrame">
   <ui:include src="#{appPreferences.includePage}"/>
</p:outputPanel>


Value
#{appPreferences.includePage}

is updated dynamically depending on what tab is selected.

This approach worked well with PrimeFaces 2.2.x. The code was following:
<p:tabView dynamic="true" cache="false" onTabChangeUpdate="mainAppFrame" tabChangeListener="#{appPreferences.onTabChange}">

                        <p:tab id="someTab"/>
                        <p:tab id="someOtherTab"/>
</p:tabView>

<p:outputPanel id="mainAppFrame">
   <ui:include src="#{appPreferences.includePage}"/>
</p:outputPanel>



But this does not work anymore with PrimeFaces 3.0RC1-SNAPSHOT. I've changed the code to be
<p:tabView dynamic="true" cache="false">
<p:ajax event="tabChange" listener="#{appPreferences.onTabChange}" update="mainApplicationFrame"/>
                        <p:tab id="someTab"/>
                        <p:tab id="someOtherTab"/>
</p:tabView>

<p:outputPanel id="mainAppFrame">
   <ui:include src="#{appPreferences.includePage}"/>
</p:outputPanel>


The problem is that appPreferences.getIncludePage() is called before appPreferences.onTabChange. This means that page is prepared for rendering before ajax listened is called. This makes impossible to update the page depending on the listener logic.

It looks like a defect but I wanted to hear some more thoughts on this.

Thanks,
Serhiy


Posts: 15072
Location: Cybertron

I think you need to monitor PrimeFaces development more like subscribing to PrimeFaces blog and visit forum more to see what's going on, this has been discussed thousands of times.

- http://wiki.primefaces.org/display/Gene ... ide+to+3.0
- http://www.primefaces.org/documentation.html
PrimeFaces Lead


Posts: 122
Can't say that I know what discussions Optimus is referring to.

As far as I'm aware the timing and ordering of event firing should not have changed between 2.2.x and 3.0.x - only the way in which listeners are defined.

But I would say your original example surely couldn't possibly have called appPreferences.onTabChange() before appPreferences.includePage(), because you would first have to render the page and display it in a browser before an action in the browser could trigger the tabChange event. And in order to render the page, you would first have to call appPreferences.includePage(). So that just doesn't make any sense.

Your revised example code for PF3 may not have pasted correctly. It won't work as it stands because your ajax event handler has update="mainApplicationFrame" instead of update="mainAppFrame"
-------
PrimeFaces 3.4, Glassfish 3.1.2, Mojarra 2.1.6


Posts: 16
The problem is not with update="mainApplicationFrame" instead of update="mainAppFrame". I was copying code samples from real application and was trying to simplify it. It's just a typo I've made in this post. It is fine in real app.

Primefaces 2.x example is working. I had it working with different PF 2.x versions! And I was following PF 3.x development.

I know that event listeners are reimplemented as ajax behaviors. But I can't find any documentation that says that listeners are called after page is re-rendered. If it is an expected behavior how to update page depending on listener logic? This is my question and issue.


Posts: 122
I still have no idea how this could possibly have worked in PF2.x.

In JSF2 ui:include is evaluated during the restore_view phase, which is well before any listener could get called. So even if you set your ajax behaviour to immediate="true" (which is an option you would not have had in PF2.x days) it would only invoke the listener during the apply_request_values, which would still be too late for your intended use.

One possible way to get this to work is to just force redisplaying the entire page after the Ajax behaviour completes. i.e.
<p:ajax event="tabChange" listener="#{appPreferences.onTabChange}" oncomplete="history.go(0);"/>
-------
PrimeFaces 3.4, Glassfish 3.1.2, Mojarra 2.1.6


Posts: 16
Thank you for the feedback. I want to ask one more question.

If I have
<p:ajax event="tabChange" listener="#{appPreferences.onTabChange}" update="xxxx"/>

Does this mean that the order of execution is following:
1. First component xxxx is updated by ajax call.
2. Only then appPreferences.onTabChange is executed

This is what I see when debugging.

If this is expected behavior this means that I can't change xxxx value depending on the listener's code. This makes me feel confused. Or am I missing something?


Posts: 122
No. Update="xxx" tells JSF what components to render in the final phase: render_response. This is always after any listeners are called.

However, ui:include is not a "component" in the normal JSF sense of the word. It is more of a UI directive. So the reason you are seeing appPreferences.includePage() being called before the listener is because it is referenced from a ui:include, which JSF evaluates during restore_view.

You will find this helpful: http://www.ninthavenue.com.au/blog/c:foreach-vs-ui:repeat-in-facelets
-------
PrimeFaces 3.4, Glassfish 3.1.2, Mojarra 2.1.6


Return to General