Lifecycle

The component class has special system methods which are called at a certain moment.

Component.prototype.constructor(element, scope)

  • element HTMLElement - html element object controlled by the component
  • scope Proxy - object to synchronize with the component template (content)
class MyComponent extends Akili.Component {
  constructor(element, scope) {
    super(element, scope);

    console.log(element === this.el); // true;
    console.log(scope === this.scope); // true;
  }
}

First of all, during the compilation it will be created an instance of the component. Constructor gets element and scope. Here you can do anything with the element and its content. It is the place where you can prepare your component to compilation: change element and set default scope values, for example.

class MyComponent extends Akili.Component {
  constructor(element, scope) {
    super(element, scope);

    element.innerHTML = '${ this.example }';
    element.setAttribute('class', '${ this.className }');

    scope.example = 'Hello!';
    scope.className = 'example';
  }
}
Cancel the compilation

You can stop the component compilation if it is necessary. It is possible only in the constructor.

class MyComponent extends Akili.Component {
  constructor(...args) {
    super(...args);

    if(!this.el.hasAttribute('x')) {
      this.cancel();
    }
  }
}

So if the element does not have attribute x, the compilation will not happen. Further steps will be stopped. Another way to stop compiling without even getting into the constructor is matches property using.

class MyComponent extends Akili.Component {
  static matches = '[x]';
}

Both examples above are equivalent

Prevent the compilation

Also you can prevent the compilation inside of the component.

class Code extends Akili.Component {
  constructor(...args) {
    super(...args);

    this.prevent();
  }
}
<code>${ example }</code>

After the compilation there will be the same code inside of the component, because the compilation was prevented.

<code>${ example }</code>

Component.prototype.created()

This is a logical extension of the constructor and will be called immediately after that, if you didn't cancel the compilation in the constructor. At this level, expressions in the component template is not parsed yet. You can't use .attr() and .store() methods here. It is good place to set default values, for example.

Component.prototype.compiled() Promise

At this level, all expressions are parsed. Component attributes, .attr() and .store() methods are available here.

Component.prototype.recompiled()

It is called on every recompilation of the component.

Component.prototype.resolved() Promise

This method is called after the full compilation of the component and all nested components, even if they use asynchronous loading of their templates. So you have access to all the children components here.

class ParentComponent extends Akili.Component {
  resolved() {
    this.child('child-component').setTitle();
  }
}

class ChildComponent extends Akili.Component {
  constructor(...args) {
    super(...args);

    this.scope.title = '';
  }

  setTitle() {
    this.scope.title = 'Look at this!';
  }
}
<parent-component>
  <child-component>
    ${ this.title }
  </child-component>
</parent-component>

During the compilation all the stages of the component occur from top to bottom and from left to right in the hierarchy. But at this stage everything is the other way: from right to left and from bottom to top.

Component.prototype.removed()

This method will be called on the component removing. You can do something here before it.