Wednesday 18 February 2015

I post a Lucee question on Stack Overflow

G'day:
Maybe you can help with this: "Associating child tag data with grandparent tag using CFC-based custom tags"?



The full repro case for this question is in my GitHub repository. I'll only reproduce the necessary bits here.

Let's say I have this usage of some custom tags:

<!--- testCfcTags.cfm --->
<cfimport taglib="cfcBasedTags" prefix="t">

Text before tags<br>
<t:grandparent gp:attr="set in grandparent">
    Text in grandparent, before parent<br>
    <t:parent p:attr="set in parent">
        Text in parent, before child<br>
        <t:child c:attr="set in child">
            Text in child<br>
        </t:child>
        Text in parent, after child<br>
    </t:parent>
    Text in grandparent, after parent<br>
</t:grandparent>
Text after tags<br>


If I was using CFM-based custom tags, and I was to want to associate data from within my implementation of the child tag with the grandparent tag, I would simply to this:

<!--- child.cfm --->
<cfif thistag.executionMode eq "end">
    <cfassociate basetag="cf_grandparent" datacollection="childAttributesForGrandparent"><!--- this line --->
    <cfassociate basetag="cf_parent" datacollection="childAttributesForParent">
</cfif>


Note I can associate directly to the grandparent tag.

I cannot work out how to do this cleanly with Lucee's CFC-based custom tags.

This is the best I can come up with:
// Child.cfc
component {

    function init(hasEndTag, parent){
        this.parent = arguments.parent;
    }

    function onEndTag(attributes, caller, generatedContent){
        writeOutput(generatedContent);
        this.parent.childattributesForParent = attributes;
        this.parent.parent.childattributesForGrandparent = attributes;
        return false;
    }

}


And in Parent.cfc I have this:
// Parent.cfc
component {

    function init(hasEndTag, parent){
        this.parent = arguments.parent;
    }

    function onEndTag(attributes, caller, generatedContent){
        writeOutput(generatedContent);
        this.parent.parentattributesForGrandparent = attributes;
        writeDump(var=this.childAttributesForParent, label="Parent childAttributesForParent");
        return false;
    }

}


That cumulative (mis-)usage of the this.parent.parent.

However that's all a bit "Heath Robinson". Given the rest of Lucee's CFC-based custom tag implementation is pretty slick, I am sure I'm just missing something. I really don't think I ought to have to burrow through the Parent to get to the Grandparent. Also it means that the code would need to differ for situations in which the Child is directly within the Grandparent. What I really need is for some tag-hierarchy to be passed between CFCs, not simply the parent.

I've googled about, but most of what's out there is written by me (which is in turn based on the blog articles originally written for Railo's implementation of this - which is what the Lucee implementation is based on).

Docs I've already read, which are no help:
Any thoughts? If so, answer on Stack Overflow pls. Cheers!

--
Adam