Custom fields can be created in just a few steps. All you need is an interaction element (like for instance a slider, a listbox or a combobox) and connect it to the Field functionality.
An interaction element provides the means for the end user to enter a certain value, just like
native elements provide in this (think of <input>
, <textarea>
and <select>
).
An example of a non native element is the
slider design pattern
described here.
For this tutorial, we assume we have a component <my-slider>
that exposes its value via property
mySliderValue
and sends an event my-slider-changed
on every value change. To make it focusable,
it has a tabindex=“0” applied.
Now we want to integrate the slider in our form framework to enrich the user interface, get
validation support and get all the other benefits of LionField.
We start of by creating a component <lion-slider>
that extends from LionField
.
Then we follow the steps below:
-
Here you return the element the user interacts with. By configuring it as a slot, it will end up in light DOM, ensuring the best accessibility for the end user.
-
The
user-input-changed
event is listened to by the FormatMixin: it should be regarded as the equivalent of theinput
event of the platform, but for custom built interaction elements. -
Every time the
user-input-changed
fires, the value of<my-slider>
is synchronized with themodelValue
of<my-slider>
. Now the cycle is complete: the modelValue connects your interaction element to all logic inside the LionField.
Steps as described can be implemented with the following javascript:
import { LionField } from '@lion/field';
import './my-slider.js';
export class LionSlider extends LionField {
// 1. Add your interaction element as ‘input slot'
get slots() {
return {
...super.slots,
input: () => document.createElement(‘my-slider’),
};
}
// 2. Proxy event `my-slider-changed` to `user-input-changed` event
connectedCallback() {
super.connectedCallback();
this.addEventListener('my-slider-changed', this._proxyChangeEvent);
}
_proxyChangeEvent() {
this._inputNode.dispatchEvent(
new CustomEvent('user-input-changed', { bubbles: true, composed: true }),
);
}
// 3. Proxy property `<my-slider>.mySliderValue` to `<lion-slider>.value`
get value() {
return Array.from(this.children).find(child => child.slot === 'input').mySliderValue;
}
set value(newV) {
Array.from(this.children).find(child => child.slot === 'input').mySliderValue = newV;
}
}
That was all. Now you can enhance your slider by writing custom validators for it or by writing a parser to get a custom modelValue type.