| 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>
`;
}
}
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>
`;
}
}
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() )
β» 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(); //-> ππ₯π₯π₯
πΊ Try CraftKit Playground:
https://github.com/craftkit/craftkit-playground

Top comments (0)