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] >>>> >>>> >>>> >>>> >>>> >>> >>> >> > >