Regarding your request for the event attribute in ActionLink. Doesn't the component EventLink solve your problem ?
http://tapestry.apache.org/tapestry5/tapestry-core/ref/org/apache/tapestry/corelib/components/EventLink.html Corin Lawson wrote: > Hi All, > > I admire Travis' ambition, but he's forgetting an ancient programming maxim: > be lazy! By that I mean there no need to implement your own Zone component > (or sub-component). I actually got this to work, but I'm not %100 satisfied. > > So the id attribute of zone doesn't allow property expansion; don't despair, > use the default. The Loop component does 'unique-ify' the ids in a > predictable manner, so let's take advantage of that! All we need is a method > to compute what the zone id is expected to be for that iteration. This would > be possible with render variables, if it weren't the fact that the second > iteration starts at zero! > > .tml snippet: > <t:loop t:source="..." t:index="currentIndex" t:value="currentValue"> > <t:zone t:id="myZone">...${currentValue}...</t:zone> > <t:actionlink t:id="myAction" t:zone="prop:currentZoneId" > t:context="currentValue">...</t:actionlink> > </t:loop> > > .java snippet: > @Component > private Zone _myZone; > > private int _currentIndex; // Getters and Setters... > private Object _currentValue; // Getters and Setters... > > public String getCurrentZoneId() { > if(_currentIndex == 0) > return "myZone"; > return "myZone_" + (_currentIndex - 1); > } > > Object onAction(_currentValue) { > setCurrentValue(_currentValue); > return _myZone; > } > > Note that it is important to pass the currentValue through the context > because I have used it's value inside the zone. Any property expansion > inside the zone needs to passed through the context otherwise Tapestry (or > more specifically the Zone component) doesn't know what iteration it is. > > Limitations: > > (*) We are stuck with Loop's unique-ifation. > (*) We must use the generic onAction event handler (unless the OnEvent > annotation does property expansion in the component attribute(?)) > (*) Don't go crazy with the currentValue, stick to the primitives. Having > said that you can always pass the currentIndex through the context and use > that to set the currentValue. > > There is a work-around these limitations. If with define an upper limit to > the size of the Loop's source list (not an unreasonable thing to do) then we > could ditch the context and be verbose to the event handler methods like so: > > Object onActionFromMyAction() { > _currentIndex = 0; > _currentValue = ...; > return _myZone; > } > > Object onActionFromMyAction_0() { > _currentIndex = 1; > _currentValue = ...; > return _myZone; > } > > Object onActionFromMyAction_1() { > _currentIndex = 2; > _currentValue = ...; > return _myZone; > } > > etc. > > In fact, it would be a fairly simple task to do this with java > instrumentation. It would be even better to have a event type attribute on > ActionLink, so that we can specify something other than action, like: > > Object onMyEventFromMyLink(currentIndex) { > ... > return _myZone; > } > > Dear Commiters, please add an event attribute to ActionLink. > > Cheers, > Corin. > > > Travis McLeskey wrote: > >> (I wasn't subscribed to the list, so I'm sorry I'm not quoting the >> rest of the thread here.) >> >> I ran into the same problem as Adriaan: it wouldn't let me use a >> property expansion for the zone's id attribute. The only way around >> this that I found was to create my own MyZone component (based on >> Tapestry's Zone.java) and add a "customId" attribute. Then, in >> MyZone.beginRender(), I replaced this: >> >> _clientId = >> _pageRenderSupport.allocateClientId(_resources.getId()); >> >> with something like: >> >> if( _resources.isBound("customId") ) >> _clientId = _customId; >> else >> _clientId = >> _pageRenderSupport.allocateClientId(_resources.getId()); >> >> Then, I made my loop look more like this: >> >> <t:loop source="items" value="item"> >> <t:actionlink zone="myzone:${item.id}">go!</t:actionlink> >> <t:myzone customid="myzone:${item.id}">in the zone?</t:zone> >> <br /> >> </t:loop> >> >> Which worked quite nicely, and it let me make a few other tweaks to >> how the Zone was rendered, like making it a instead of a <div>. >> >> >> >> However, that was only the first Zone-related hurdle. The next was >> that I couldn't find any examples in the documentation of how to >> actually provide the new content for the zone when the user clicks the >> link. After a lot of time digging through the code (and learning >> javascript!), I found the (or at least *a*) way to do it. I added this >> method to my class: >> >> public Object onActionFromUpdatezone(final long id) { >> JSONObject result = new JSONObject(); >> result.put("content", "The new content for the Zone's <div>. >> Fresh from the server!"); >> return result; >> } >> >> (Note: I gave the ActionLink an id: "updatezone") >> >> >> >> The next problem was that Zones in Tapestry currently can't do much >> other than query the server for new content, put that content in the >> <div>, and then call your "show" or "update" methods, if you specified >> them. You can't have it do something other than hit the server when >> the link is clicked, and you can't process the content before putting >> it in the <div>. Well, at least you can't do these things without the >> magic of javascript. My eventual solution is probably going to break >> in some future release of Tapestry, and it may provoke some frowns, >> but I circumvented all of the Zone-specific javascript code in >> Tapestry be redefining Tapestry.initializeZones. The javascript below >> is for an ActionLink that works as an expand/collapse button for the >> Zone. The first time you expand the zone, it downloads the content >> from the server and stores it in memory. After that, it doesn't need >> to hit the server again. Note that this code doesn't support the inner >> "t-zone-update" <div> that Tapestry's built-in javascript supports. >> >> >> MyObj = { >> linkZone: function (link, zone) { >> zone = $(zone); >> link = $(link); >> var expanded = false; >> var origHTML = zone.innerHTML; >> var fullHTML; >> >> link.onclick = function(event) { >> if( expanded ) { >> zone.innerHTML = origHTML; >> link.innerHTML = "expand"; >> expanded = false; >> } else { >> if( !zone.everPopulated ) { >> var successHandler = function(transport) { >> var response = transport.responseText; >> fullHTML = eval("(" + response + ")").content; >> zone.innerHTML = fullHTML; >> }; >> var request = new Ajax.Request(link.href, { onSuccess : >> successHandler }); >> zone.everPopulated = true; >> } else { >> zone.innerHTML = fullHTML; >> } >> link.innerHTML = "collapse" >> expanded = true; >> } >> return false; >> }; >> } >> }; >> >> Tapestry.initializeZones = function(zoneSpecs, linkSpecs) { >> $A(linkSpecs).each(function (spec) >> { >> MyObj.linkZone(spec[0],spec[1]); >> }); >> }; >> >> >> >> Hope that helps! >> Travis >> >> >> >> >> >> On Feb 8, 2008, at 11:40 PM, Travis McLeskey wrote: >> >> >>> When an ActionLink and Zone appear together in a loop like this: >>> >>> <t:loop source="items" value="item"> >>> <t:actionlink zone="myzone">go!</t:actionlink> >>> <t:zone t:id="myzone">in the zone?</t:zone> >>> <br /> >>> </t:loop> >>> >>> Clicking the "go!" link from any iteration only affects the Zone >>> from the first iteration. How do I connect each ActionLink to its >>> corresponding Zone? I tried injecting the Zone into the java class >>> and then using zone="${thezone.id}" in the actionlink, but then each >>> ActionLink was connected to the Zone from the *previous* iteration. >>> >>> Thanks! >>> Travis >>> >>> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: [EMAIL PROTECTED] >> For additional commands, e-mail: [EMAIL PROTECTED] >> >> >> >> > >