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.
You can get any attribute value in the component property attrs after the compilation.
class MyComponent extends Akili.Component {
compiled() {
console.log(this.attrs.title === 'Hello'); // true
}
}
<my-component title="Hello"></my-component>
We can change or delete an attribute in the component and it will change the corresponding value in the element.
class MyComponent extends Akili.Component {
compiled() {
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
}
}
<my-component title="Hello" x="${ this.someParentScopeValue }"></my-component>
By default, the attribute expressions of the most components use the 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 attribute scope
If you need to have the current component scope inside 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>
Attribute handling
There are two ways for attributes handling. The first is a callback using.
class MyComponent extends Akili.Component {
compiled() {
this.attr('my-attribute', val => console.log(val === 'test'))
}
}
You can also pass the camel case name of the attribute myAttribute.
class MyComponent extends Akili.Component {
compiled() {
const fn = () => {};
// callback is called on start (if this.attrs.hasOwnProperty('myAttribute')) and on change
this.attr('myAttribute', fn);
// callback is called only on change
this.attr('myAttribute', fn, { callOnStart: false });
// callback is called on start and on change
this.attr('myAttribute', fn, { callOnStart: true });
// callback is called on any attribute change
this.attr((value, attrKey) => {});
}
}
The second is the scope property binding.
class MyComponent extends Akili.Component {
compiled() {
// double binding
this.attr('my-title', 'title');
console.log(this.scope.title); // 'Hello'
// don't get the attribute change, but trigger the scope property event
this.attr('my-title', 'title', { get: false });
// don't trigger the event, but get the attribute change
this.attr('my-title', 'title', { set: false });
setTimeout(() => {
this.scope.title = 'Hi';
}, 1000);
}
}
<my-component my-title="Hello" on-my-title="${ console.log(event.detail) // 'Hi' }"></my-component>
So you can get the attribute change in the scope property. And vice versa, automatically trigger an event with the specified name when you change the scope property.
Component.prototype.attr(name, handler, options) undefined
- name string - attribute name
- handler string | string[] | function - scope property or a function to link
- [options] Object - options, for example, { callOnStart: false }
This function creates the link with the attribute.
Component.prototype.unattr(name, handler) undefined
- name string - attribute name
- handler string | string[] | function - scope property or a function to unlink
This function removes the link with the attrtibute.
Boolean attributes
Some attributes in 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 such attributes, there is a special variable booleanAttributes.
class MyComponent extends Akili.Component {
static booleanAttributes = ['my-attribute'];
compiled() {
this.attr('myAttribute', val => console.log(val === true))
}
}
<my-component my-attribute="Hello"></my-component>
<my-component my-attribute></my-component>
<my-component my-attribute="${ 1 === 1 }"></my-component>
And example for false:
class MyComponent extends Akili.Component {
static booleanAttributes = ['my-attribute'];
compiled() {
this.attr('myAttribute', val => console.log(val === false))
}
}
<my-component></my-component>
<my-component my-attribute="${ 1 !== 1 }"></my-component>
The default boolean attributes are in Akili.htmlBooleanAttributes. In addition, some system components use their own.