You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@myfaces.apache.org by Richard Wallace <rw...@thewallacepack.net> on 2005/06/13 20:17:53 UTC

Errant event firing

Hello,

I'm having another problem with my select list and the value changed 
event listener.  I have the following tag:

<h:selectManyListbox id="organizations" 
value="#{contactHandler.selectedOrganizations}" 
valueChangeListener="#{contactHandler.handleOrganizationChanged}" 
onchange="submit()" immediate="true">

This is for an "Edit Contact" page so when the page is initially loaded 
there is an organization selected.  The problem that I'm having is that 
when I click the update button to invoke the appropriate action handler 
it is never called.  The page just reloads.  If I click the update 
button a second time it does call the action handler.

I did a trace of the phases with a PhaseListener and found that it is 
jumping from the apply request values phase to the render response 
phase.  So I added some logging in the places I call the 
FacesContext.renderReponse() method and lo and behold the 
handleOrganizationChanged() event handler is being called in spite of 
nothing on the page having been changed.  To investigate further I 
logged the events old value and the new value and found that the old 
value was empty when it shouldn't have been.

Is this a side effect of the event handling being declared as being 
immediate?  What can I do to fix this?

Thanks again for all the help,
Rich

Re: Errant event firing

Posted by Martin Marinschek <ma...@gmail.com>.
I was going to propose x:saveState, but x:inputHidden and forceId is
of course working as well!

Both are MyFaces extensions, by the way!

regards,

Martin

On 6/14/05, Richard Wallace <rw...@thewallacepack.net> wrote:
> Richard Wallace wrote:
> 
> > Richard Wallace wrote:
> >
> >> Hello,
> >>
> >> I'm having another problem with my select list and the value changed
> >> event listener.  I have the following tag:
> >>
> >> <h:selectManyListbox id="organizations"
> >> value="#{contactHandler.selectedOrganizations}"
> >> valueChangeListener="#{contactHandler.handleOrganizationChanged}"
> >> onchange="submit()" immediate="true">
> >>
> >> This is for an "Edit Contact" page so when the page is initially
> >> loaded there is an organization selected.  The problem that I'm
> >> having is that when I click the update button to invoke the
> >> appropriate action handler it is never called.  The page just
> >> reloads.  If I click the update button a second time it does call the
> >> action handler.
> >>
> >> I did a trace of the phases with a PhaseListener and found that it is
> >> jumping from the apply request values phase to the render response
> >> phase.  So I added some logging in the places I call the
> >> FacesContext.renderReponse() method and lo and behold the
> >> handleOrganizationChanged() event handler is being called in spite of
> >> nothing on the page having been changed.  To investigate further I
> >> logged the events old value and the new value and found that the old
> >> value was empty when it shouldn't have been.
> >>
> >> Is this a side effect of the event handling being declared as being
> >> immediate?  What can I do to fix this?
> >
> >
> > Ok, I found the problem and it's entirely my fault.  But it brings up
> > another question.  Basically all my page backing beans are request
> > scoped and this is an edit page so I need to pass in the id of the
> > contact to edit.  I did this in the getContact() accessor method which
> > checks if the contact is null and if it is gets the contact id from
> > the external context parameter map.  This is all well and good when I
> > initially go into the edit page with the url
> > http://localhost:8080/contact/edit.jsf?contactId=11.
> >
> > In the form I try and carry this through with a hidden form element
> > called contactId thinking that I should still be able to lookup the
> > external context parameter value for "contactId" and get the right
> > thing.  That is, of course, wrong because the actual form element name
> > is like "_id1:contactId".  So the reason it comes up with the empty
> > list of selected organizations is because it's using a newly
> > constructed object and not one loaded from the backend.
> >
> > So now my question is what is the best way to carry the id across page
> > reloads like this?  I've seen the method where you would have the
> > currentContactId be a JSF managed bean property and then pass in
> > param.contactId.  But that runs into the same kind of problem.  The
> > other method I've seen for doing this sort of thing is to make the
> > actual link the user clicks on to get to the page a <h:commandLink>
> > element bound to an option that sets the current contact in a session
> > scoped backing bean and then does a redirect to the actual edit page.
> > I don't like this for a number of reasons, one being the session
> > scoped backing bean and the other being that users can't bookmark the
> > URL.  I'll have to discuss this with some people here to see if the
> > latter really is an issue or not, but I'd like to get the feedback of
> > people on the mailing list that have done this before.  So, what's the
> > most commonly accepted practice on how to handle this?  The session
> > scoped backing bean which wraps the actual data model object?  Or is
> > there a better way?
> 
> Well I found a couple of solutions to this problem.  I'm not sure either
> is the best solution but they both seem to work well enough.
> 
> One solution was to add <x:saveState
> value="#{contactHandler.selectedOrganizations}"> element.  After doing
> some testing it seems this causes the selectedOrganizations property to
> be set in the restore values phase before even any immediate events are
> handled.  So it seems like it might be a good rule of thumb to use
> <x:saveState> on any values that you need in the event handler.
> 
> In this case, however, the better solution was to use a a myfaces
> extension and use <x:inputHidden id="contactId" forceId="true"> to make
> sure the element has the name that the backing bean uses to load the
> actual data object.
> 
> Rich
> 
> 
>

Re: Errant event firing

Posted by Richard Wallace <rw...@thewallacepack.net>.
Richard Wallace wrote:

> Richard Wallace wrote:
>
>> Hello,
>>
>> I'm having another problem with my select list and the value changed 
>> event listener.  I have the following tag:
>>
>> <h:selectManyListbox id="organizations" 
>> value="#{contactHandler.selectedOrganizations}" 
>> valueChangeListener="#{contactHandler.handleOrganizationChanged}" 
>> onchange="submit()" immediate="true">
>>
>> This is for an "Edit Contact" page so when the page is initially 
>> loaded there is an organization selected.  The problem that I'm 
>> having is that when I click the update button to invoke the 
>> appropriate action handler it is never called.  The page just 
>> reloads.  If I click the update button a second time it does call the 
>> action handler.
>>
>> I did a trace of the phases with a PhaseListener and found that it is 
>> jumping from the apply request values phase to the render response 
>> phase.  So I added some logging in the places I call the 
>> FacesContext.renderReponse() method and lo and behold the 
>> handleOrganizationChanged() event handler is being called in spite of 
>> nothing on the page having been changed.  To investigate further I 
>> logged the events old value and the new value and found that the old 
>> value was empty when it shouldn't have been.
>>
>> Is this a side effect of the event handling being declared as being 
>> immediate?  What can I do to fix this?
>
>
> Ok, I found the problem and it's entirely my fault.  But it brings up 
> another question.  Basically all my page backing beans are request 
> scoped and this is an edit page so I need to pass in the id of the 
> contact to edit.  I did this in the getContact() accessor method which 
> checks if the contact is null and if it is gets the contact id from 
> the external context parameter map.  This is all well and good when I 
> initially go into the edit page with the url 
> http://localhost:8080/contact/edit.jsf?contactId=11.
>
> In the form I try and carry this through with a hidden form element 
> called contactId thinking that I should still be able to lookup the 
> external context parameter value for "contactId" and get the right 
> thing.  That is, of course, wrong because the actual form element name 
> is like "_id1:contactId".  So the reason it comes up with the empty 
> list of selected organizations is because it's using a newly 
> constructed object and not one loaded from the backend.
>
> So now my question is what is the best way to carry the id across page 
> reloads like this?  I've seen the method where you would have the 
> currentContactId be a JSF managed bean property and then pass in 
> param.contactId.  But that runs into the same kind of problem.  The 
> other method I've seen for doing this sort of thing is to make the 
> actual link the user clicks on to get to the page a <h:commandLink> 
> element bound to an option that sets the current contact in a session 
> scoped backing bean and then does a redirect to the actual edit page.  
> I don't like this for a number of reasons, one being the session 
> scoped backing bean and the other being that users can't bookmark the 
> URL.  I'll have to discuss this with some people here to see if the 
> latter really is an issue or not, but I'd like to get the feedback of 
> people on the mailing list that have done this before.  So, what's the 
> most commonly accepted practice on how to handle this?  The session 
> scoped backing bean which wraps the actual data model object?  Or is 
> there a better way?

Well I found a couple of solutions to this problem.  I'm not sure either 
is the best solution but they both seem to work well enough.

One solution was to add <x:saveState 
value="#{contactHandler.selectedOrganizations}"> element.  After doing 
some testing it seems this causes the selectedOrganizations property to 
be set in the restore values phase before even any immediate events are 
handled.  So it seems like it might be a good rule of thumb to use 
<x:saveState> on any values that you need in the event handler.

In this case, however, the better solution was to use a a myfaces 
extension and use <x:inputHidden id="contactId" forceId="true"> to make 
sure the element has the name that the backing bean uses to load the 
actual data object.

Rich



Re: Errant event firing

Posted by Richard Wallace <rw...@thewallacepack.net>.
Richard Wallace wrote:

> Hello,
>
> I'm having another problem with my select list and the value changed 
> event listener.  I have the following tag:
>
> <h:selectManyListbox id="organizations" 
> value="#{contactHandler.selectedOrganizations}" 
> valueChangeListener="#{contactHandler.handleOrganizationChanged}" 
> onchange="submit()" immediate="true">
>
> This is for an "Edit Contact" page so when the page is initially 
> loaded there is an organization selected.  The problem that I'm having 
> is that when I click the update button to invoke the appropriate 
> action handler it is never called.  The page just reloads.  If I click 
> the update button a second time it does call the action handler.
>
> I did a trace of the phases with a PhaseListener and found that it is 
> jumping from the apply request values phase to the render response 
> phase.  So I added some logging in the places I call the 
> FacesContext.renderReponse() method and lo and behold the 
> handleOrganizationChanged() event handler is being called in spite of 
> nothing on the page having been changed.  To investigate further I 
> logged the events old value and the new value and found that the old 
> value was empty when it shouldn't have been.
>
> Is this a side effect of the event handling being declared as being 
> immediate?  What can I do to fix this?

Ok, I found the problem and it's entirely my fault.  But it brings up 
another question.  Basically all my page backing beans are request 
scoped and this is an edit page so I need to pass in the id of the 
contact to edit.  I did this in the getContact() accessor method which 
checks if the contact is null and if it is gets the contact id from the 
external context parameter map.  This is all well and good when I 
initially go into the edit page with the url 
http://localhost:8080/contact/edit.jsf?contactId=11.

In the form I try and carry this through with a hidden form element 
called contactId thinking that I should still be able to lookup the 
external context parameter value for "contactId" and get the right 
thing.  That is, of course, wrong because the actual form element name 
is like "_id1:contactId".  So the reason it comes up with the empty list 
of selected organizations is because it's using a newly constructed 
object and not one loaded from the backend.

So now my question is what is the best way to carry the id across page 
reloads like this?  I've seen the method where you would have the 
currentContactId be a JSF managed bean property and then pass in 
param.contactId.  But that runs into the same kind of problem.  The 
other method I've seen for doing this sort of thing is to make the 
actual link the user clicks on to get to the page a <h:commandLink> 
element bound to an option that sets the current contact in a session 
scoped backing bean and then does a redirect to the actual edit page.  I 
don't like this for a number of reasons, one being the session scoped 
backing bean and the other being that users can't bookmark the URL.  
I'll have to discuss this with some people here to see if the latter 
really is an issue or not, but I'd like to get the feedback of people on 
the mailing list that have done this before.  So, what's the most 
commonly accepted practice on how to handle this?  The session scoped 
backing bean which wraps the actual data model object?  Or is there a 
better way?

Thanks
Rich