Zone-Update inside a form inside a block (with generated ids) not working
-------------------------------------------------------------------------

                 Key: TAP5-1746
                 URL: https://issues.apache.org/jira/browse/TAP5-1746
             Project: Tapestry 5
          Issue Type: Bug
          Components: tapestry-core
    Affects Versions: 5.3
            Reporter: Christian Riedel
            Priority: Critical


Zone-Updates are not working under certain conditions when being rendered 
inside a block.

If an outer zone receives a zone-update the components inside the content of 
the delegated block will have generated ids:
{{noformat}}
    <t:zone t:id="outerZone">
        <t:delegate t:to="block" />
    </t:zone>
{{noformat}}

--> after a zone-update the "block" property resolves to the following block:

{{noformat}}
    <t:block t:id="editBlock">
        <t:form t:id="editForm">
           
            <t:select t:id="updateSelectBox" t:model="values" 
t:value="selected" t:zone="updateZone" />
 
            <t:zone t:id="updateZone">
                <t:select t:id="theOtherValue" t:model="otherValues" 
t:value="other" blankOption="never" />
            </t:zone>           
            
        </t:form>
    </t:block>
{{noformat}}

The select component "updateSelectBox" won't find the zone "updateZone" since 
the real clientId has a randomly generated number appended.
To circumvent this feature one can write a getter to obtain the generated id 
each time the block renders:

{{noformat}}
            <t:select t:id="updateSelectBox" t:model="values" 
t:value="selected" t:zone="prop:updateZoneId" />
{{noformat}}
{{noformat}}
    public String getUpdateZoneId() {

        return updateZone.getClientId();
    }
{{noformat}}

However, this won't work as expected, either.
Firstly because the clientId is always null at that point. It's being called 
before the zone's beginRender method is invoked.
Secondly because you need this client id in the event handler as well. Even if 
you'd be able to get the id at this point, the execution of the processReply 
method in tapestry.js will fail because it can't find the zone. The id has been 
generated once more and is not yet known to the client:

{{noformat}}
    @OnEvent(component = "updateSelectBox", value = 
EventConstants.VALUE_CHANGED)
    void onValueSelected() {

        // this will also fail on the client side
        ajaxResponseRenderer.addRender(getUpdateZoneId(), updateZone);
    }
{{noformat}}

Now what I found being the only workaround is to store the client id once it's 
generated, i.e. when the block renders the first time.
But as I stated earlier the id is null before beginRender is called. So another 
workaround must be applied: 

Switch the order of the components:
{{noformat}}
    <t:block t:id="editBlock">
        <t:form t:id="editForm">
            
            <t:zone t:id="updateZone">
                <t:select t:id="theOtherValue" t:model="otherValues" 
t:value="other" blankOption="never" />
            </t:zone>
            
            <t:select t:id="updateSelectBox" t:model="values" 
t:value="selected" t:zone="prop:updateZoneId" />
            
        </t:form>
    </t:block>
{{noformat}}

Now that the "updateZone" renders before the "updateSelectBox", 
"prop:updateZoneId" is able to return the correct id.

Please make the first example work! It should not be necessary to deal with the 
generated ids. Tapestry.js should implement some magic-code to find out the 
correct zone if "updateZone" is referenced in the template. Since all 
components within the same block have the same generated value appended it 
might actually be possible to find the correct zone.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to