On Sun, Feb 14, 2010 at 3:07 PM, Thiago H. de Paula Figueiredo <
thiag...@gmail.com> wrote:

> On Sun, 14 Feb 2010 00:10:02 -0200, Nathan Kopp <nathan.k...@gmail.com>
> wrote:
>
>  There are two things preventing this from working:
>> First, Tapestry does not replay the loop when processing the eventlink
>> (like it did in the 3.x and 4.x days).  Therefore, "fooLoopVar" never gets
>> changed from its default of null.
>>
>
> Tapestry 5 doesn't have the rewind phase like previous versions had. And
> that's a very good thing, because it was quite complicated to understand and
> make it work. You should use the context parameter of EventLink and
> ActionLink to pass information to the event handler method.


Understood. While I always liked the (poorly named) "rewind phase," I do
understand that lots of other people disliked it and I don't mind that it is
gone. However, I'm trying to find an alternative method to achieve the same
end goal (i.e. effective handling of highly dynamic custom components nested
inside loops).


>  I tried using the "context" parameter of the eventlink component, but
>> since events start at the deepest level and bubble up,
>>
>
> It starts at the EventLink instance level, not from the deepest one.
>

That's what I meant by "deepest level"... sorry for not being clearer.
 However, in my case the NPE happens one layer deeper than the EventLink
instance level.  This means that the NPE happens BEFORE my event handler has
a chance do anything with the context.  T5 bails out with the NPE before it
ever gets to the level containing the EventLink.


> I got the null pointerexception before I could use the context for anything
>> useful at the outer
>> (page) level.
>>
>
> This looks like a bug in your code, most probably by working in a T4-ish
> way in T5.


Well, it's certainly a "bug" in that I'm trying to do something that T5
doesn't seem to handle out-of-the-box.  However, that doesn't change the
fact that I need to achieve my end goal.  I'm searching for the T5-style way
of doing what I need to do.  I'd like to stay "in the box" as much as
possible, but I'm not afraid to step outside the box as long as the code is
"pretty."


> In Test.java, I added:
>>    String onPassivate() {
>>        return fooLoopVar==null?null:fooLoopVar.getName();
>>    }
>>
>
> You shouldn't rely in a variable used as a Loop object (in this case,
> fooLoopVar), as T5 doesn't have a rewind phase.


First, I need to rely on a loop variable.  Period.  The component exists in
the context of one iteration of the loop.  Without the loop variable, the
component wouldn't need to exist.  I'll rephrase my problem like this: "I
need to rely on the loop variable, but it is null when tapestry processes
the click from the eventlink, so I need to find a way to make it not null
while tapestry processes that eventlink click... and specifically make it
equal the a value for a specific iteration through the loop... the iteration
that was occurring at the time the eventlink was being rendered."

>From what I understand, the page activation context (onPassivate/onActivate)
IS one of the T5 ways of handling the loop variable in lieu of the rewind
phase.  In T5, you must encode the state in the next user input using the
URL or hidden form fields.  I know of three ways to do this:
1) and formState for a loop inside a form.
2) page activation context;
2) context for eventlink, actionlink, and form;

#1 won't work for me because my loop is not enclosed in a form, and the
action is an eventlink, not a form submission.
#2 won't work because my loop is not happening at the page level, but rather
at an intermediate level
#3 wont' work because my loop is not happening at the evenlink level, but
rather at an intermediate level

Note: it might be possible to get the page activation context to work... but
I need some way to communicate the info from the loop to the page activation
context, and from the page activation context back to the loop.  I might
make a custom Loop component that is capable of storing its current state
into the page activation context.  I think I can use a ComponentResources to
handle this.


>  Basically, I need something that works like the page activation context,
>> but generalized to work with any component at any level of the component
>> tree.
>>
>
> Inject ComponentEventLinkEncoder and use its
> decodePageRenderRequest(Request request) method (when rendering) or
> decodePageRenderRequest(Request request) (when handling an event). Both
> methods return an object that contains the page activation context.


Hmmm... an interesting idea.  I guess I could replace
ComponentEventLinkEncoder with a custom implementation, but that sounds a
little scary.  I think I'll try the custom Loop component that stores state
in the page activation context.  Thanks for the idea of injecting something
into my component, though... that spurred my idea of injecting
ComponentResources so that my component can communicate with the underlying
page to store state in the activation context.  :)

I hope this is starting to make sense.

-Nathan

Reply via email to