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