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

Reply via email to