You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by Richard Lewis-Shell <rl...@mac.com> on 2005/05/11 06:37:38 UTC

Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

This could also work for ActionLink too.  I re-read the blog/thread on 
improved listener methods, and those changes seem to fit in with using 
immediate and deferred listeners to remember rewind state.  So, let me 
firm this up a bit.

Imagine.html:
<a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
getCurrentBar() }">click me</a>

Imagine.java:
public void clickMe(IRequestCycle cycle)
{
     doSomethingWithBar((Bar)cycle.getListenerParameters()[0]);
}

That's written for ActionLink, but could work the same for LinkSubmit, 
Submit, or ImageSubmit too.  The real idea here is to get the 
link/submit component to set the listener parameters at the time the 
link/submit is 'detected' - ie. when the immediate listener would have 
been fired.

This seems simpler than my previous suggestion of extending the 
IActionListener interface.

By the way, could the listener parameters be made to work by name 
instead of position?  I realise Java uses positional parameters so there 
is a bit of a mismatch, but I'd prefer to name parameters, epsecially 
when the calling code is well separated from the code using the 
parameters, which is the case when the parameters are specified in the 
template/specification, and consumed in the Java class - there is no 
compiler to help here.

Using named paremeters would mean this:

Imagine.html:
<a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
'foo' : getCurrentBar() }">click me</a>

Imagine.java:
public void clickMe(IRequestCycle cycle)
{
     doSomethingWithBar((Bar)cycle.getListenerParameters("foo"));
}

Given that there are those that prefer positional parameters, and those 
that prefer named parameters, perhaps both could be implemented?

Richard

Richard Lewis-Shell wrote:
> When will a deferred listener be *constructed* (as oppsosed to invoked)? 
>  Immediately, or also deferred?  I am hoping it is immediate.
> 
> In previous Tapestry projects we have created wrappers for the submit 
> components to implement this (using selected/tag), and have made use of 
> a deferredListener parameter as Mind Bridge suggests.  However, because 
> we were using selected/tag to pull this off, perhaps we could use 
> selected/tag instead (the immediate listener was usually used to catch 
> the current rewind state so that it could be processed later by the 
> deferred listener).  Although now thinking about it - in complex 
> pages/components (e.g. nested Foreachs), there was more than one object 
> to select/tag, so there would still be use for allowing customised state 
> catching.
> 
> We typcially handle this using the following pattern:
> public IActionListener getButtonListener()
> {
>     // make note of any important state when the listener is constructed
>     // in final variables so they are accessible later when the
>     // deferred listener is invoked
>     final MyClass1 myObject = getCurrentValueFromOuterForeach();
>     final MyClass2 myOtherObject = getCurrentValueFromInnerForeach();
>     return new IActionListener()
>     {
>         public void actionTriggered(IComponent component, IRequestCycle 
> cycle)
>         {
>             // use the state gathered earlier
>             doSomething(myObject, myOtherObject);
>         }
>     };
> }
> 
> I wonder if it's worth supporting this directly, rather than relying on 
> constructor timing:
> public interface IFormActionListener extends IActionListener
> {
>     public void deferredActionTriggered(IComponent component, 
> IRequestCycle cycle);
> }
> 
> This would allow replacing the above example with:
> public void getButtonListener()
> {
>     return new IFormActionListener()
>     {
>         private MyClass1 myObject;
>         private MyClass2 myOtherObject;
> 
>         public void actionTriggered(IComponent component, IRequestCycle 
> cycle)
>         {
>             myObject = getCurrentValueFromOuterForeach();
>             myOtherObject = getCurrentValueFromInnerForeach();
>         }
> 
>         public void deferredActionTriggered(IComponent component, 
> IRequestCycle cycle)
>         {
>             doSomething(myObject, myOtherObject);
>         }
>     };
> }
> 
> More typing :-( But clearer :-)
> 
> Richard
> 
> PS. It would actually be possible to do even better than that and have 
> the 'immediate'/contruction state remembered by Tapestry automatically, 
> and then pass that state into the deferred listener - would just require 
> telling the Submit et al components what state to remember.  Reminds me 
> of the recent parameter thread for DirectLink...
> 
> Mind Bridge wrote:
> 
>> Hi,
>>
>> This was initial idea as well, but I am curious: what happens if the 
>> Submits are in a loop?
>> Isn't the behaviour of the component now different as there is no good 
>> way to determine which iteration of the loop was "clicked"? The 
>> suggestion of someone else in the list (cannot find the message right 
>> now) was to have 'deferredListener' in addition to 'listener' instead 
>> of a boolean 'deferred'. This guarantees that people account for the 
>> different behaviour when coding.
>>
>> Also, assuming the current interface, shouldn't 'defer' default to 
>> 'false'? 'true' appears quite backward incompatible in the light of 
>> the above.
>>
>>
>> Howard M. Lewis Ship (JIRA) wrote:
>>
>>>     [ http://issues.apache.org/jira/browse/TAPESTRY-166?page=all ]
>>>     Howard M. Lewis Ship closed TAPESTRY-166:
>>> -----------------------------------------
>>>
>>>     Resolution: Fixed
>>>    Fix Version: 4.0
>>>
>>> Added a defer parameter to Submit and ImageSubmit that defaults to true.
>>> Updated the component documentation for Submit and ImageSubmit.
>>> Wrotes unit tests for Submit and ImageSubmit.
>>> Are there other submit-like components?  In the WML framework, perhaps?
>>>
>>>  
>>>
>>>> Allow Submits to defer invoking their listener
>>>> ----------------------------------------------
>>>>
>>>>         Key: TAPESTRY-166
>>>>         URL: http://issues.apache.org/jira/browse/TAPESTRY-166
>>>>     Project: Tapestry
>>>>        Type: Bug
>>>>  Components: Framework
>>>>    Versions: 3.0
>>>> Environment: Operating System: All
>>>> Platform: All
>>>>    Reporter: Alex Ieong
>>>>    Assignee: Howard M. Lewis Ship
>>>>     Fix For: 4.0
>>>>   
>>>
>>>
>>>
>>>  
>>>
>>>> Quoted from the developer's guide (Chapter 6 , Services and forms): 
>>>> "The Form component doesn't terminate the rewind cycle until after 
>>>> all of its wrapped components have had a chance to render. It then 
>>>> notifies its own listener."
>>>> But it doesn't seems to be the case. There are 2 PropertySelection 
>>>> components and 2 Submit components in the same Form component. When 
>>>> the Submit components are after the PropertySelection components, 
>>>> everything is ok.
>>>> But when the Submit components are BETWEEN the PropertySelection 
>>>> components, the value in the later PropertySelection component is 
>>>> not assigned.
>>>>   
>>>
>>>
>>>
>>>  
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On May 11, 2005, at 7:11 AM, Richard Lewis-Shell wrote:

>>> Imagine.html:
>>> <a jwcid="@ActionLink" defer="true" listener="clickMe"   
>>> parameters="{ 'foo' : getCurrentBar() }">click me</a>
>>>
>> Imagine this instead:
>>     <a jwcid="@ActionLink" defer="true" listener="clickMe"   
>> foo="currentBar">click me</a>
>> This is how I've implemented this with my ParamLink/ParamService.  
>> I  pass a Map with named key/value pairs as the first listener  
>> parameter.
>>
>
> You win!  Does that prevent informal parameters from being rendered  
> as attributes?

Yes.  But for an <a> there really isn't need for anything informal, I  
don't think.  Formal parameters could be declared for things like  
"class" and "style".

     Erik


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Richard Lewis-Shell <rl...@mac.com>.
>> Imagine.html:
>> <a jwcid="@ActionLink" defer="true" listener="clickMe"  parameters="{ 
>> 'foo' : getCurrentBar() }">click me</a>
> 
> 
> Imagine this instead:
> 
>     <a jwcid="@ActionLink" defer="true" listener="clickMe"  
> foo="currentBar">click me</a>
> 
> This is how I've implemented this with my ParamLink/ParamService. I  
> pass a Map with named key/value pairs as the first listener parameter.

You win!  Does that prevent informal parameters from being rendered as 
attributes?

Richard

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Erik Hatcher <er...@ehatchersolutions.com>.
On May 11, 2005, at 12:37 AM, Richard Lewis-Shell wrote:
> By the way, could the listener parameters be made to work by name  
> instead of position?  I realise Java uses positional parameters so  
> there is a bit of a mismatch, but I'd prefer to name parameters,  
> epsecially when the calling code is well separated from the code  
> using the parameters, which is the case when the parameters are  
> specified in the template/specification, and consumed in the Java  
> class - there is no compiler to help here.
>
> Using named paremeters would mean this:
>
> Imagine.html:
> <a jwcid="@ActionLink" defer="true" listener="clickMe"  
> parameters="{ 'foo' : getCurrentBar() }">click me</a>

Imagine this instead:

     <a jwcid="@ActionLink" defer="true" listener="clickMe"  
foo="currentBar">click me</a>

This is how I've implemented this with my ParamLink/ParamService. I  
pass a Map with named key/value pairs as the first listener parameter.

     Erik


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Nathan Kopp <nk...@mailshell.com>.
"Richard Lewis-Shell" <rl...@mac.com> wrote...
> >
> > Why doesn't ActionLink have a deferrable listener?
>
> Probably because there isn't such a nice place to defer to - the Submit
> etc components live in a form so their listener can be deferred until
> the form rewind is complete.  Perhaps ActionLink could allow being
> deferred until the page rewind is complete.

I would think that even for the Submit components, it might be more useful
to defer until the page rewind is complete.  When the direct service is used
(which is the default), then these are basically the same, since only the
form is rewound (that is, unless the deferred listeners are triggered before
the form's listener... I haven't looked closely at the new deferred
listeners yet).

The reason I say that it might be useful to always defer until the full page
rewind is complete is that the listener may change part of the model which
affects how other componenets outside of the form are rendered.  If the form
uses the Action service instead of the Direct service, than this could make
a difference.  And if the form does use the Direct service, then it really
doesn't matter either way.

If the deferred listeners fire after the page rewind is complete, but the
user wants the deferred listeners to fire _before_ the Form's listener
fires, then the user could make the form's listener deferred, too.  So,
then, when the list of deferred listeners are executed after the page
rewind, they are executed in the proper order (FIFO queue), executing the
Submit listener first, followed by the Form's listener.

> > Are these parameters always encoded in the url (or form) like
DirectLink's
> > service parameters?  Or can they be computed during the rewind process?
>
> Computed during rewind.

That's what I was hoping for, since (IMHO) it is the most useful for form
submissions.

I proposed some ideas over in the "users" group about possibly combining
some of these new enhancements, such as Howard's DirectLink parameter
enhancements (which are encoded in the URL), deferred listeners (which, at
the time, I thought was an original idea), and more listener triggers for
various componenets.

Basically, I think that combining these features could improve consistency
in the components.  i.e. On any component's listener, that listener could be
deferred, you could include parameters, and those parameters could be
computed during rewind or could be embedded in the form or URL.  Then you
could also make every submitting component by default use the Direct service
(where only the containing Form is rewound), but optionally use the Action
service. (Right now you can do this with the Form component, though as a
user I think this might make more sense for this option to be set in the
Submit component.)  Doing this could allow ActionLink and DirectLink (and
possibly PageLink) to be consolidated into a single component.  (I don't
think I'm the first to suggest this idea, either.)

-Nathan


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Richard Lewis-Shell <rl...@mac.com>.
>>Ignore the suggestion to also incorporate this into ActionLink - this
>>really only makes sense for components with deferable listeners.
> 
> Why doesn't ActionLink have a deferrable listener?

Probably because there isn't such a nice place to defer to - the Submit 
etc components live in a form so their listener can be deferred until 
the form rewind is complete.  Perhaps ActionLink could allow being 
deferred until the page rewind is complete.

> Are these parameters always encoded in the url (or form) like DirectLink's
> service parameters?  Or can they be computed during the rewind process?

Computed during rewind.

Richard

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Nathan Kopp <nk...@mailshell.com>.
"Richard Lewis-Shell" <rl...@mac.com> wrote:

> Ignore the suggestion to also incorporate this into ActionLink - this
> really only makes sense for components with deferable listeners.

Why doesn't ActionLink have a deferrable listener?

Are these parameters always encoded in the url (or form) like DirectLink's
service parameters?  Or can they be computed during the rewind process?

-Nathan


---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Richard Lewis-Shell <rl...@mac.com>.
Ignore the suggestion to also incorporate this into ActionLink - this 
really only makes sense for components with deferable listeners.

Richard Lewis-Shell wrote:
> I've implemented this for Submit (really just to test the idea) and it 
> seems to work.  This is a little less radical than Erik's ParamLink 
> parameters - not as nice to use admittedly, but less likely to cause 
> problems with informal parameters.  I like this because it makes 
> Submit/ImageSubmit/LinkSubmit/ActionLink feel the same as the new 
> DirectLink.
> 
> Anyone got any issues with me adding a "parameters" parameter to Submit, 
>  ImageSubmit, LinkSubmit (still requires defer support), ActionLink? 
> (these are positional parameters - I still prefer named, but positional 
> is easier to start with)
> 
> Richard
> 
> Richard Lewis-Shell wrote:
> 
>> This could also work for ActionLink too.  I re-read the blog/thread on 
>> improved listener methods, and those changes seem to fit in with using 
>> immediate and deferred listeners to remember rewind state.  So, let me 
>> firm this up a bit.
>>
>> Imagine.html:
>> <a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
>> getCurrentBar() }">click me</a>
>>
>> Imagine.java:
>> public void clickMe(IRequestCycle cycle)
>> {
>>     doSomethingWithBar((Bar)cycle.getListenerParameters()[0]);
>> }
>>
>> That's written for ActionLink, but could work the same for LinkSubmit, 
>> Submit, or ImageSubmit too.  The real idea here is to get the 
>> link/submit component to set the listener parameters at the time the 
>> link/submit is 'detected' - ie. when the immediate listener would have 
>> been fired.
>>
>> This seems simpler than my previous suggestion of extending the 
>> IActionListener interface.
>>
>> By the way, could the listener parameters be made to work by name 
>> instead of position?  I realise Java uses positional parameters so 
>> there is a bit of a mismatch, but I'd prefer to name parameters, 
>> epsecially when the calling code is well separated from the code using 
>> the parameters, which is the case when the parameters are specified in 
>> the template/specification, and consumed in the Java class - there is 
>> no compiler to help here.
>>
>> Using named paremeters would mean this:
>>
>> Imagine.html:
>> <a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
>> 'foo' : getCurrentBar() }">click me</a>
>>
>> Imagine.java:
>> public void clickMe(IRequestCycle cycle)
>> {
>>     doSomethingWithBar((Bar)cycle.getListenerParameters("foo"));
>> }
>>
>> Given that there are those that prefer positional parameters, and 
>> those that prefer named parameters, perhaps both could be implemented?
>>
>> Richard
>>
>> Richard Lewis-Shell wrote:
>>
>>> When will a deferred listener be *constructed* (as oppsosed to 
>>> invoked)?  Immediately, or also deferred?  I am hoping it is immediate.
>>>
>>> In previous Tapestry projects we have created wrappers for the submit 
>>> components to implement this (using selected/tag), and have made use 
>>> of a deferredListener parameter as Mind Bridge suggests.  However, 
>>> because we were using selected/tag to pull this off, perhaps we could 
>>> use selected/tag instead (the immediate listener was usually used to 
>>> catch the current rewind state so that it could be processed later by 
>>> the deferred listener).  Although now thinking about it - in complex 
>>> pages/components (e.g. nested Foreachs), there was more than one 
>>> object to select/tag, so there would still be use for allowing 
>>> customised state catching.
>>>
>>> We typcially handle this using the following pattern:
>>> public IActionListener getButtonListener()
>>> {
>>>     // make note of any important state when the listener is constructed
>>>     // in final variables so they are accessible later when the
>>>     // deferred listener is invoked
>>>     final MyClass1 myObject = getCurrentValueFromOuterForeach();
>>>     final MyClass2 myOtherObject = getCurrentValueFromInnerForeach();
>>>     return new IActionListener()
>>>     {
>>>         public void actionTriggered(IComponent component, 
>>> IRequestCycle cycle)
>>>         {
>>>             // use the state gathered earlier
>>>             doSomething(myObject, myOtherObject);
>>>         }
>>>     };
>>> }
>>>
>>> I wonder if it's worth supporting this directly, rather than relying 
>>> on constructor timing:
>>> public interface IFormActionListener extends IActionListener
>>> {
>>>     public void deferredActionTriggered(IComponent component, 
>>> IRequestCycle cycle);
>>> }
>>>
>>> This would allow replacing the above example with:
>>> public void getButtonListener()
>>> {
>>>     return new IFormActionListener()
>>>     {
>>>         private MyClass1 myObject;
>>>         private MyClass2 myOtherObject;
>>>
>>>         public void actionTriggered(IComponent component, 
>>> IRequestCycle cycle)
>>>         {
>>>             myObject = getCurrentValueFromOuterForeach();
>>>             myOtherObject = getCurrentValueFromInnerForeach();
>>>         }
>>>
>>>         public void deferredActionTriggered(IComponent component, 
>>> IRequestCycle cycle)
>>>         {
>>>             doSomething(myObject, myOtherObject);
>>>         }
>>>     };
>>> }
>>>
>>> More typing :-( But clearer :-)
>>>
>>> Richard
>>>
>>> PS. It would actually be possible to do even better than that and 
>>> have the 'immediate'/contruction state remembered by Tapestry 
>>> automatically, and then pass that state into the deferred listener - 
>>> would just require telling the Submit et al components what state to 
>>> remember.  Reminds me of the recent parameter thread for DirectLink...
>>>
>>> Mind Bridge wrote:
>>>
>>>> Hi,
>>>>
>>>> This was initial idea as well, but I am curious: what happens if the 
>>>> Submits are in a loop?
>>>> Isn't the behaviour of the component now different as there is no 
>>>> good way to determine which iteration of the loop was "clicked"? The 
>>>> suggestion of someone else in the list (cannot find the message 
>>>> right now) was to have 'deferredListener' in addition to 'listener' 
>>>> instead of a boolean 'deferred'. This guarantees that people account 
>>>> for the different behaviour when coding.
>>>>
>>>> Also, assuming the current interface, shouldn't 'defer' default to 
>>>> 'false'? 'true' appears quite backward incompatible in the light of 
>>>> the above.
>>>>
>>>>
>>>> Howard M. Lewis Ship (JIRA) wrote:
>>>>
>>>>>     [ http://issues.apache.org/jira/browse/TAPESTRY-166?page=all ]
>>>>>     Howard M. Lewis Ship closed TAPESTRY-166:
>>>>> -----------------------------------------
>>>>>
>>>>>     Resolution: Fixed
>>>>>    Fix Version: 4.0
>>>>>
>>>>> Added a defer parameter to Submit and ImageSubmit that defaults to 
>>>>> true.
>>>>> Updated the component documentation for Submit and ImageSubmit.
>>>>> Wrotes unit tests for Submit and ImageSubmit.
>>>>> Are there other submit-like components?  In the WML framework, 
>>>>> perhaps?
>>>>>
>>>>>  
>>>>>
>>>>>> Allow Submits to defer invoking their listener
>>>>>> ----------------------------------------------
>>>>>>
>>>>>>         Key: TAPESTRY-166
>>>>>>         URL: http://issues.apache.org/jira/browse/TAPESTRY-166
>>>>>>     Project: Tapestry
>>>>>>        Type: Bug
>>>>>>  Components: Framework
>>>>>>    Versions: 3.0
>>>>>> Environment: Operating System: All
>>>>>> Platform: All
>>>>>>    Reporter: Alex Ieong
>>>>>>    Assignee: Howard M. Lewis Ship
>>>>>>     Fix For: 4.0
>>>>>>   
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>  
>>>>>
>>>>>> Quoted from the developer's guide (Chapter 6 , Services and 
>>>>>> forms): "The Form component doesn't terminate the rewind cycle 
>>>>>> until after all of its wrapped components have had a chance to 
>>>>>> render. It then notifies its own listener."
>>>>>> But it doesn't seems to be the case. There are 2 PropertySelection 
>>>>>> components and 2 Submit components in the same Form component. 
>>>>>> When the Submit components are after the PropertySelection 
>>>>>> components, everything is ok.
>>>>>> But when the Submit components are BETWEEN the PropertySelection 
>>>>>> components, the value in the later PropertySelection component is 
>>>>>> not assigned.
>>>>>>   
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>  
>>>>>
>>>>
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>>>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>>>
>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org


Re: Improved listeners can work for non-DirectLink componenets too (was Re: [jira] Closed: (TAPESTRY-166) Allow Submits to defer invoking their listener)

Posted by Richard Lewis-Shell <rl...@mac.com>.
I've implemented this for Submit (really just to test the idea) and it 
seems to work.  This is a little less radical than Erik's ParamLink 
parameters - not as nice to use admittedly, but less likely to cause 
problems with informal parameters.  I like this because it makes 
Submit/ImageSubmit/LinkSubmit/ActionLink feel the same as the new 
DirectLink.

Anyone got any issues with me adding a "parameters" parameter to Submit, 
  ImageSubmit, LinkSubmit (still requires defer support), ActionLink? 
(these are positional parameters - I still prefer named, but positional 
is easier to start with)

Richard

Richard Lewis-Shell wrote:
> This could also work for ActionLink too.  I re-read the blog/thread on 
> improved listener methods, and those changes seem to fit in with using 
> immediate and deferred listeners to remember rewind state.  So, let me 
> firm this up a bit.
> 
> Imagine.html:
> <a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
> getCurrentBar() }">click me</a>
> 
> Imagine.java:
> public void clickMe(IRequestCycle cycle)
> {
>     doSomethingWithBar((Bar)cycle.getListenerParameters()[0]);
> }
> 
> That's written for ActionLink, but could work the same for LinkSubmit, 
> Submit, or ImageSubmit too.  The real idea here is to get the 
> link/submit component to set the listener parameters at the time the 
> link/submit is 'detected' - ie. when the immediate listener would have 
> been fired.
> 
> This seems simpler than my previous suggestion of extending the 
> IActionListener interface.
> 
> By the way, could the listener parameters be made to work by name 
> instead of position?  I realise Java uses positional parameters so there 
> is a bit of a mismatch, but I'd prefer to name parameters, epsecially 
> when the calling code is well separated from the code using the 
> parameters, which is the case when the parameters are specified in the 
> template/specification, and consumed in the Java class - there is no 
> compiler to help here.
> 
> Using named paremeters would mean this:
> 
> Imagine.html:
> <a jwcid="@ActionLink" defer="true" listener="clickMe" parameters="{ 
> 'foo' : getCurrentBar() }">click me</a>
> 
> Imagine.java:
> public void clickMe(IRequestCycle cycle)
> {
>     doSomethingWithBar((Bar)cycle.getListenerParameters("foo"));
> }
> 
> Given that there are those that prefer positional parameters, and those 
> that prefer named parameters, perhaps both could be implemented?
> 
> Richard
> 
> Richard Lewis-Shell wrote:
> 
>> When will a deferred listener be *constructed* (as oppsosed to 
>> invoked)?  Immediately, or also deferred?  I am hoping it is immediate.
>>
>> In previous Tapestry projects we have created wrappers for the submit 
>> components to implement this (using selected/tag), and have made use 
>> of a deferredListener parameter as Mind Bridge suggests.  However, 
>> because we were using selected/tag to pull this off, perhaps we could 
>> use selected/tag instead (the immediate listener was usually used to 
>> catch the current rewind state so that it could be processed later by 
>> the deferred listener).  Although now thinking about it - in complex 
>> pages/components (e.g. nested Foreachs), there was more than one 
>> object to select/tag, so there would still be use for allowing 
>> customised state catching.
>>
>> We typcially handle this using the following pattern:
>> public IActionListener getButtonListener()
>> {
>>     // make note of any important state when the listener is constructed
>>     // in final variables so they are accessible later when the
>>     // deferred listener is invoked
>>     final MyClass1 myObject = getCurrentValueFromOuterForeach();
>>     final MyClass2 myOtherObject = getCurrentValueFromInnerForeach();
>>     return new IActionListener()
>>     {
>>         public void actionTriggered(IComponent component, 
>> IRequestCycle cycle)
>>         {
>>             // use the state gathered earlier
>>             doSomething(myObject, myOtherObject);
>>         }
>>     };
>> }
>>
>> I wonder if it's worth supporting this directly, rather than relying 
>> on constructor timing:
>> public interface IFormActionListener extends IActionListener
>> {
>>     public void deferredActionTriggered(IComponent component, 
>> IRequestCycle cycle);
>> }
>>
>> This would allow replacing the above example with:
>> public void getButtonListener()
>> {
>>     return new IFormActionListener()
>>     {
>>         private MyClass1 myObject;
>>         private MyClass2 myOtherObject;
>>
>>         public void actionTriggered(IComponent component, 
>> IRequestCycle cycle)
>>         {
>>             myObject = getCurrentValueFromOuterForeach();
>>             myOtherObject = getCurrentValueFromInnerForeach();
>>         }
>>
>>         public void deferredActionTriggered(IComponent component, 
>> IRequestCycle cycle)
>>         {
>>             doSomething(myObject, myOtherObject);
>>         }
>>     };
>> }
>>
>> More typing :-( But clearer :-)
>>
>> Richard
>>
>> PS. It would actually be possible to do even better than that and have 
>> the 'immediate'/contruction state remembered by Tapestry 
>> automatically, and then pass that state into the deferred listener - 
>> would just require telling the Submit et al components what state to 
>> remember.  Reminds me of the recent parameter thread for DirectLink...
>>
>> Mind Bridge wrote:
>>
>>> Hi,
>>>
>>> This was initial idea as well, but I am curious: what happens if the 
>>> Submits are in a loop?
>>> Isn't the behaviour of the component now different as there is no 
>>> good way to determine which iteration of the loop was "clicked"? The 
>>> suggestion of someone else in the list (cannot find the message right 
>>> now) was to have 'deferredListener' in addition to 'listener' instead 
>>> of a boolean 'deferred'. This guarantees that people account for the 
>>> different behaviour when coding.
>>>
>>> Also, assuming the current interface, shouldn't 'defer' default to 
>>> 'false'? 'true' appears quite backward incompatible in the light of 
>>> the above.
>>>
>>>
>>> Howard M. Lewis Ship (JIRA) wrote:
>>>
>>>>     [ http://issues.apache.org/jira/browse/TAPESTRY-166?page=all ]
>>>>     Howard M. Lewis Ship closed TAPESTRY-166:
>>>> -----------------------------------------
>>>>
>>>>     Resolution: Fixed
>>>>    Fix Version: 4.0
>>>>
>>>> Added a defer parameter to Submit and ImageSubmit that defaults to 
>>>> true.
>>>> Updated the component documentation for Submit and ImageSubmit.
>>>> Wrotes unit tests for Submit and ImageSubmit.
>>>> Are there other submit-like components?  In the WML framework, perhaps?
>>>>
>>>>  
>>>>
>>>>> Allow Submits to defer invoking their listener
>>>>> ----------------------------------------------
>>>>>
>>>>>         Key: TAPESTRY-166
>>>>>         URL: http://issues.apache.org/jira/browse/TAPESTRY-166
>>>>>     Project: Tapestry
>>>>>        Type: Bug
>>>>>  Components: Framework
>>>>>    Versions: 3.0
>>>>> Environment: Operating System: All
>>>>> Platform: All
>>>>>    Reporter: Alex Ieong
>>>>>    Assignee: Howard M. Lewis Ship
>>>>>     Fix For: 4.0
>>>>>   
>>>>
>>>>
>>>>
>>>>
>>>>  
>>>>
>>>>> Quoted from the developer's guide (Chapter 6 , Services and forms): 
>>>>> "The Form component doesn't terminate the rewind cycle until after 
>>>>> all of its wrapped components have had a chance to render. It then 
>>>>> notifies its own listener."
>>>>> But it doesn't seems to be the case. There are 2 PropertySelection 
>>>>> components and 2 Submit components in the same Form component. When 
>>>>> the Submit components are after the PropertySelection components, 
>>>>> everything is ok.
>>>>> But when the Submit components are BETWEEN the PropertySelection 
>>>>> components, the value in the later PropertySelection component is 
>>>>> not assigned.
>>>>>   
>>>>
>>>>
>>>>
>>>>
>>>>  
>>>>
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>>
>>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
>>
>>
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org
> 
> 

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org