DEV Community

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

Posted on β€’ Edited 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

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly β€” using the tools and languages you already love!

Learn More

Top comments (0)

Sentry image

See why 4M developers consider Sentry, β€œnot bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

πŸ‘‹ Kindness is contagious

DEV is better (more customized, reading settings like dark mode etc) when you're signed in!

Okay