DEV Community

Cover image for Accessing instance variable from template literal - craftkit code pattern
CraftkitJS
CraftkitJS

Posted on • Updated on

Accessing instance variable from template literal - craftkit code pattern

Template for craftkit is defined by template method. It only requires returning HTML starting with single node. Usually you will use JavaScript template literal to define your view's structure. (see more: GitHub document)

template method gets a String argument componentId. It is bound to its instance via widnow[componentId] if you set Craft.Core.Defaults.ALLOW_COMPONENT_SHORTCUT = true.

So below two codes have same behavior.

Access via this:

class Example extends Craft.UI.View {
    constructor(options){
        super(options);
        this.data = { val:'Hello!' };
    }
    template(componentId){
        return `
            <div id="root" class="root">
                ${this.data.val}
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

Access via componentId:

class Example extends Craft.UI.View {
    constructor(options){
        super(options);
        this.data = { val:'Hello!' };
    }
    template(componentId){
        return `
            <div id="root" class="root">
                ${window[componentId].data.val}
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

When you access to the instance variable, it is natural style to use this.

But in JavaScript function context, this points function itself. So you have to use componentId to access inside its instance.

class Example extends Craft.UI.View {
    action(str){
        alert(str);
    }
    template(componentId){
        return `
            <div id="root" class="root">
                <div onclick="${componentId}.action('World!')">
                    Hello
                </div>
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

Take a look:

<!-- Good -->
<div onclick="${componentId}.action('World!')">
    Hello
</div>

<!-- Uncaught TypeError: this.action is not a function -->
<div onclick="this.action('BUG!')">
    Hello
</div>

<!-- Uncaught TypeError: Cannot read property 'val' of undefined -->
<div>
    componentId is evaluated as String
    ${componentId.data.val}
</div>
Enter fullscreen mode Exit fullscreen mode

BTW, the argument componentId can be named as you like.

class Example extends Craft.UI.View {
    constructor(options){
        super(options);
        this.data = { val:'Hello!' };
    }
    action(str){
        alert(str);
    }
    template(self){
        return `
            <div id="root" class="root">
                <div onclick="${self}.action('World!')">
                    ${this.data.val} traditional looks and feel
                </div>
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

NOTE

Above examples are runnable on playground.

var view = new Example();
view.loadView();
Craft.Core.Context.getRootViewController().appendSubView(view);
Enter fullscreen mode Exit fullscreen mode

🛺 Try CraftKit Playground:
https://github.com/craftkit/craftkit-playground

Top comments (0)