DEV Community

Cover image for How Component and componentId covers and exposes its structure - inside craftkit
CraftkitJS
CraftkitJS

Posted on • Edited on

How Component and componentId covers and exposes its structure - inside craftkit

Alt Text

Prop desc.
this.view shadow host
this.shadow shadow root
this.root component root based on template

this.view, this.shadow and this.root are Craft.UI.View's basic property that is defined by Craft.Core.Component the top level class of all views.

this.view is the top level DOM element of your component, having unique componentId. This is the Shadow Host of your component.

this.shadow is Shadow Root of your component, attached to this.view (Shadow Host) by open mode.

this.root is the first child of your template, and it is appended to the this.shadow (Shadow Root).

Your template is under the Shadow Root. Therefore CSS class name and DOM ID never conflict across the craftkit application. This is the first key technology of craftkit to enable comfortable OOP by encapsulating Component definition.

For example:

class Vehicle extends Craft.UI.View {
    whoami(){
        return this.shadow.getElementById('text').innerHTML;
    }
    style(componentId){
        return `
            .root { color:red; }
        `;
    }
    template(componentId){
        return `
            <div id="root" class="root">
                <span id="text">I'm Vehicle</span>
            </div>
        `;
    }
}
class Bike extends Vehicle {
    style(componentId){
        return super.style(componentId) + `
            .root { color:blue; }
        `;
    }
    template(componentId){
        return `
            <div id="root" class="root">
                <span id="text">I'm Bike.</span>
            </div>
        `;
    }
}
class Car extends Vehicle {
    style(componentId){
        return super.style(componentId) + `
            .root { color:purple; }
        `;
    }
    template(componentId){
        return `
            <div id="root" class="root">
                <span id="text">I'm Car.</span>
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

Bike and Car both cascade .root CSS class from Vehicle, but both root class independently applied and never conflict.

By the principle of Shadow DOM specification, you cannot access inside of your component DOM element via its ID from out side of your component.

But your can access inside of your component's element via componentId from any where you want.

Instantiated component is registered to the Craft.Core.ComponentStack by its unique componentId. If you set Craft.Core.Defaults.ALLOW_COMPONENT_SHORTCUT to true at boot time, you can also use the componentId as global variable. This is the second key technology of craftkit.

This feature is used to call instance method from rendered template.

class DangerousTruck extends Car {
    ignite(){
        this.shadow.getElementById('text').innerHTML = "🚛🔥🔥🔥";
    }
    cooldown(){
        this.shadow.getElementById('text').innerHTML = "I'm COOL Truck 😄";
    }
    style(componentId){
        return super.style(componentId) + `
            .root { color:purple; }
        `;
    }
    template(componentId){
        return `
            <div id="root" class="root">
                <span id="text" onclick="${componentId}.ignite()">
                    I'm dangerous Truck.
                </span>
            </div>
        `;
    }
}
Enter fullscreen mode Exit fullscreen mode

When you click the text, it ignites the truck!

Of course, you can call ignite method from global by something like this:

Object.keys(Craft.Core.ComponentStack.container)
.filter( id => id.match('Dangerous') )
.map( danger => window[danger].cooldown() )
Enter fullscreen mode Exit fullscreen mode

※ Object.keys for Craft.Core.ComponentStack.container returns array of componentId. This is String. So it is accessing from window object.

NOTE

Above examples are runnable on playground.

var bike_view = new Bike();
bike_view.loadView();
Craft.Core.Context.getRootViewController().appendSubView(bike_view);

var car_view = new Car();
car_view.loadView();
Craft.Core.Context.getRootViewController().appendSubView(car_view);

bike_view.shadow.getElementById('text').innerHTML; //-> I'm Bike
bike_view.whoami();                                //-> I'm Bike

car_view.root.style.color = 'purple' //-> make 'I'm Car.' purple

var truck_view = new DangerousTruck();
truck_view.loadView();
Craft.Core.Context.getRootViewController().appendSubView(truck_view);

truck_view.ignite(); //-> 🚛🔥🔥🔥
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)