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]