Oh I get now... I tried using "${component:myZone}.id" as the zone attribute of the link but all the variations I tried just rendered something like this:
"[EMAIL PROTECTED]" I couldn't work out how to access properties of the component. Any ideas? But it gave me another idea to free my code from getCurrentZoneId method. I am now significantly satisfied with the following solution. It makes for one very lean POJO. .tml snippet: <t:loop t:source="myList" t:index="var:index" t:value="currentValue"> <t:zone t:id="myZone">...${currentValue}...</t:zone> <t:eventlink t:event="myUpdate" t:zone="prop:myZone.clientId" t:context="var:index">...</t:actionlink> </t:loop> .java snippet: @Component private Zone _myZone; // Getters and Setters... private List _myList; // Getters and Setters... private Object _currentValue; // Getters and Setters... Object onMyUpdate(index) { setCurrentValue(_myList.get(index)); return _myZone; } QED Cheers, Corin HugoPalma wrote: > > No problem, just glad i could help :o) > > Regarding the component prefix, have you tried using it ? Because it > really is just what that line says. You just have to provide the id of a > component and the expression will resolve to the component instance. > Example: > > <t:pagelink t:id="mypagelink" page="Start">Home</t:pagelink> > > <t:delegate to="component:mypagelink"/> > > This would render the pagelink component twice. > > Corin Lawson wrote: >> Awesome! >> >> Sorry, I overlooked that one ... I'm just a noob :P >> >> Thanks for sharing HugoPalma. >> >> All that I want now is the ability do away with the currentZoneId >> property. >> Could someone explain the component prefix of a binding expression. The >> Component Parameters page of the tapestry-core guide simply says: >> >> 'The id of another component within the same template' >> >> Could someone provide an example of how it's used? >> >> >> HugoPalma wrote: >> >>> 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] >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >>>> >>> >> >> > > -- View this message in context: http://www.nabble.com/T5%3A-ActionLink-Zone-components-inside-a-loop-tp15374193p15480337.html Sent from the Tapestry - User mailing list archive at Nabble.com. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]