JSF

Just some random things that might make your JSF experience nicer

Tuesday, April 04, 2006

ValueChangeListeners what you need to know

Ok now I never quite figured this one out. The idea behind value change listeners should be simple. However EVERYONE gets confused because they don’t execute when expected.


Ok what you might of missed! Value change listeners are fired before the Setter methods are called.

So what?

Well this means any changes you make to variables from your value change method will be overwritten when the setters are called.


So I commonly hear just call FacesContext.getCurrentInstace.renderResponse()

so this should skip the phases meaning the setters are not called and go directly to the render response phase.

At first glance yes perfect it works.

What it doesn't do is update the VIEW ?
The getters are never called on your managed bean properties which means that the view is never updated with the values you change from you valueChangeListener.

How annoying :) so how to get around this.

1) You can force JSF to recreate the view.

Make a navigation rule to navigate back to the same page and call it in your value change method.

FacesContext.getCurrentInstance().getApplication().getNavigationHandler().handleNavigation(FacesContext.getCurrentInstance(),null,"test");

< navigation-rule >
< from-view-id > /myPage.jsp< /from-view-id >
< navigation-case >
< from-outcome > test< /from-outcome >
< to-view-id > / myPage.jsp< /to-view-id >
< /navigation-case >
< /navigation-rule >



2) Move the value change event to the update model phase.

This way your setters are called before your value change event something like

public void changeMethod(ValueChangeEvent event)
{
PhaseId phaseId = event.getPhaseId();
String oldValue = (String) event.getOldValue();
String newValue = (String) event.getNewValue();
if (phaseId.equals(PhaseId.ANY_PHASE))
{
event.setPhaseId(PhaseId.UPDATE_MODEL_VALUES);
event.queue();
}
else if (phaseId.equals(PhaseId.UPDATE_MODEL_VALUES))
{
// do you method here
}
}

3) Create your UICcomponents in your bean (use binding) and from your value change method call the .setMethod() on the UIComponents, then call the FacesContext.getCurrentInstance().renderResponse();
It appears the getters are called if you update the UI components directly.




I know these seems like hacks but for now I have not found any better solutions to what really seems like a flaw in the design

24 Comments:

Blogger HeMan10 said...

Hi,

//do you method here

What goes in place of the comment in the above code snippet?

Thanks
HeMan

2:00 PM  
Blogger Dave said...

Whatever code you would have put in your value changed listener the rest is just the "wrapping" hack to get the phase to the correct position

7:44 PM  
Blogger Dave said...

hey that is my blog also found another soultion

a valueChangedListener that acts as a action listener


http://www.irian.at/myfaces-sandbox/valueChangeNotifier.jsf

3:54 PM  
Blogger qdog1028 said...

Hi,

This works to update the model with what you want...what it does not do is skip validation...do you need the context.renderResponse()? And if so...where should you put it? I've tried it with no luck...

12:26 PM  
Blogger Vun Loon said...

intuitive article.
I try binding h:selectOneMenu to UISelectOne. in the value change event listener method, I called UISelectOne.setSubmittedValue() to the the value that I want. So that the subsequent apply value phase will have the correct value set.

8:45 PM  
Blogger Phil said...

perfect article, i like the solution with the shifting phases. You saved my weekend ;)

2:05 AM  
Blogger Ryan said...

I agree with Phil. Shifting the phases seems like the least evil of the hacks. It saved me from using property binding and has few side-effects.

7:53 PM  
Blogger Ravi C said...

hi Dave,

nice to c an article on value change listeners. We are using Ice faces and we observed that the value change listener and setters and getters are getting called multiple times. is there any reson why like this??

one more thing, how far is it advisable to use HTML tags in JSF. Because writing banners etc would not be possible with out HTML.

1:19 PM  
Blogger Ravi C said...

Also, the value change listeners are not working in tabbed panel of icefaces... any ideas???

1:21 PM  
Blogger M!L@N $h@h said...

Hi,

Is the 2nd approach useful when i am using the Bean in request scope. I have tried the same... but it is failing.

3:25 AM  
Blogger M!L@N $h@h said...

Hi,

does the 2nd approach works when the bean is in reques scope ? I have tried, but the values are getting reset.

3:26 AM  
Blogger Y.M.Prasanthi said...

hi it is very good it helped me very much thank you. I am developing site on struts see and send me your response site is http://strutsland.info

4:13 AM  
Blogger Dave said...

I found that if you use the following, it forces the view to rebuild its self.
FacesContext.getCurrentInstance().getViewRoot().getChildren().clear();

getFacesContext().renderResponse();

The draw back to this technique is that any changes in the view are lost unless they are retrieved before clearing the children.

1:19 PM  
Blogger wizard said...

hi I am sat from india.

do you have any idea about jsf with richfaces .

i need Tree event handling could you please tel me how can i do this.

9:58 PM  
Blogger Kusi said...

This comment has been removed by the author.

8:11 AM  
Blogger BVN Reddy said...

Lifesaver blog item

8:42 AM  
Blogger 简阅 said...

if use with icefaces partial submit, it is better to use method 3 ... because method 1 will affect other UIComponent on the same page which also using Partial Submit

8:55 PM  
Blogger Natali said...

Hey

I have almost given up with this issue!!! Till I have encountered this solution!!!

You're the best, Thanks

Natalie

2:51 AM  
Blogger Rama Murthy said...

Great post, thanks for sharing

10:27 PM  
Blogger Alejandro said...

you are the best!! greetings from spain!!!

6:42 PM  
Blogger 卡利歐 said...

Thanks. It help me a lot

7:25 PM  
Blogger Johnny Delta said...

I'm really starting to hate JSF. It seems like everything you expect to work doesn't, and you need to find some hack to make it do the most basic things. Struts 2 was way better IMHO, well thought out and worked the way you'd expect.

10:56 PM  
Blogger Mathias Kölbl said...

saved my day

5:31 AM  
Blogger Ransico said...

Great tips, #2 saved the day!

7:35 PM  

Post a Comment

<< Home