Attributes

Attributes are the important part of the component. They allow it to be isolated from the outside world, but at the same time have a connection with it. You can find interesting information about attributes binding here.

You can get any attribute value in the component property attrs after compilation.

class MyComponent extends Akili.Component {
  compiled() {
    console.log(this.attrs.title === 'Hello'); // true
  }
}
<my-component title="Hello"></my-component>

You can change or delete attribute in the component any time and it will change the value in the element too.

class MyComponent extends Akili.Component {
  compiled() {
    setTimeout(() => {
      console.log(this.el.getAttribute('title')); // Hello
      console.log(this.el.hasAttribute('x')); // true

      this.attrs.title === 'Goodbye';
      delete this.attrs.x;

      console.log(this.el.getAttribute('title')); // Goodbye
      console.log(this.el.hasAttribute('x')); // false
    });
  }
}

If you change or delete an attribute with a binding or an event emitter, you will remove these features from them and they will become common attributes.

<my-component title="Hello" x="${ this.someParentScopeValue }"></my-component>

By default the attribute expressions of the most components include a parent scope.

class ParentComponent extends Akili.Component {
  created() {
    this.scope.test = 'parent';
  }
}

class ChildComponent extends Akili.Component {
  created() {
    this.scope.test = 'child';
  }

  compiled() {
    console.log(this.attrs.test === 'child'); // false
    console.log(this.attrs.test === 'parent'); // true
  }
}
<parent-component>
  <child-component test="${ this.test }"></child-component>
</parent-component>

The scope of an attribute

If you want to have the scope of the current component in the attribute expression, you have to use controlAttributes option.

class ParentComponent extends Akili.Component {
  created() {
    this.scope.test = 'parent';
  }
}

class ChildComponent extends Akili.Component {
  static controlAttributes = true;

  created() {
    this.scope.test = 'child';
  }

  compiled() {
    console.log(this.attrs.test === 'child'); // true
    console.log(this.attrs.test === 'parent'); // false
  }
}
<parent-component>
  <child-component test="${ this.test }"></child-component>
</parent-component>

Boolean attributes

Some attributes in the html are boolean. For example the checkbox attribute checked. If it exists, it is already true.

<input type="checkbox" checked /> == <input type="checkbox" checked="checked"/>

To manage these attributes, there is a special variable booleanAttributes.

class MyComponent extends Akili.Component {
  static booleanAttributes = ['my-attribute'];

  changedMyAttribute(value) {
    console.log(value === true) // true
  }
}
<my-component my-attribute="Hello"></my-component>
<my-component my-attribute></my-component>
<my-component my-attribute="${ 1 === 1 }"></my-component>

And false example:

class MyComponent extends Akili.Component {
  static booleanAttributes = ['my-attribute'];

  changedMyAttribute(value) {
    console.log(value === false) // true
  }
}
<my-component></my-component>
<my-component my-attribute="${ 1 !== 1 }"></my-component>

You can find all default boolean attributes in Akili.htmlBooleanAttributes. In addition, some system components use their own.