# How To >> Create a custom field ||20
```js script
import { html, css, LitElement } from '@mdjs/mdjs-preview';
import { LionField } from '@lion/form-core';
import '@lion/form-core/define';
import '../../docs/fundamentals/systems/form/assets/h-output.js';
// A) the custom [slot=input] or 'HTMLElementWithValue'
class DummySlider extends LitElement {
// A1) it should have a .value property of type 'string'
static properties = { value: String, reflect: true };
static styles = [
css`
:host {
display: block;
padding-top: 16px;
padding-bottom: 16px;
}
[part='rail'] {
position: relative;
display: block;
background: #eee;
height: 8px;
border-radius: 8px;
}
[part='thumb'] {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
font-size: 10px;
background: black;
color: white;
border-radius: 50%;
height: 24px;
width: 24px;
top: 50%;
transform: translateY(-50%);
transition: left 0.5s ease 0s;
}
`,
];
constructor() {
super();
this.value = '0';
this.addEventListener('click', ev => {
this.value = `${Math.round(
((ev.clientX - this.getClientRects()[0].x) / this.offsetWidth) * 5,
)}`;
// A2) it should have a way to tell LionField its value changed
this.dispatchEvent(new Event('dummy-slider-changed', { bubbles: true }));
});
}
connectedCallback() {
super.connectedCallback();
this.setAttribute('tabindex', 0);
}
render() {
return html`
${this.value}
`;
}
}
if (!customElements.get('dummy-slider')) {
customElements.define('dummy-slider', DummySlider);
}
```
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 [LionField](../../components/input/overview.md).
> In case you want to extend a native element, follow [Extend a native Input](./extend-a-native-input.md).
## A) an interaction element
An interaction element (.\_inputNode) 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](https://www.w3.org/TR/wai-aria-practices-1.1/#slider) described here.
For this tutorial, we create a dummy component 'dummy-slider' that exposes its value via
property `.value` and sends an event `dummy-slider-changed` on every value change.
To make it focusable, it has a tabindex=“0” applied.
```js preview-story
export const createAnInteractiveElement = () => {
// A) the custom [slot=input] or 'HTMLElementWithValue'
class DummySlider extends LitElement {
// A1) it should have a .value property of type 'string'
static properties = { value: String };
constructor() {
super();
this.value = 0;
this.addEventListener('click', ev => {
this.value = `${Math.round(
((ev.clientX - this.getClientRects()[0].x) / this.offsetWidth) * 5,
)}`;
// A2) it should have a way to tell LionField its value changed
this.dispatchEvent(new Event('dummy-slider-changed', { bubbles: true }));
});
}
connectedCallback() {
super.connectedCallback();
this.setAttribute('tabindex', 0);
}
render() {
return html`
${this.value}
`;
}
}
return html``;
};
```
## B) your LionField extension
Now we want to integrate the slider in our form system to enrich the user interface, get
validation support and all other [benefits of LionField](../../components/input/overview.md).
We start by creating a component `` that extends from `LionField`.
Then we follow the steps below:
- **Add your interaction element**
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.
- **Connect modelValue**
The `user-input-changed` event is listened to by the FormatMixin: it should be regarded as the
equivalent of the `input` event of the platform, but for custom built interaction elements.
You now synchronized [modelValue](../../fundamentals/systems/form/model-value.md), which can be regarded as
the glue to integrate all other functionality like parsing/formatting/serializing, validating,
tracking interaction states etc.
> N.B. Make sure you never override other property getters than the one mentioned in this tutorial,
> because those properties will loose their reactivity (they won't be considered anymore in the
> update loop of LitElement).
> Whenever a .modelValue/.formattedValue/.serializedValue needs to be computed, use
> [parser/formatter/serializer](../../docs/../fundamentals/systems/form/formatting-and-parsing.md)
Implement with the following code:
```js preview-story
export const createAField = () => {
// B) your extension with all the Field goodness...
class SliderField extends LionField {
// B1) Add your interaction element as ‘input slot'
get slots() {
return {
...super.slots,
input: () => document.createElement('dummy-slider'),
};
}
// B2) Connect modelValue
constructor() {
super();
this.addEventListener('dummy-slider-changed', ev => {
ev.stopPropagation();
this.dispatchEvent(new Event('user-input-changed'));
});
}
get value() {
// Remember we should always return type 'string' here
return this._inputNode.value;
}
set value(newV) {
this._inputNode.value = newV;
}
}
customElements.define('slider-field', SliderField);
return html`
`;
};
```
That was all!
Now that your .modelValue is connected your component is fully compatible with our form system
> Is your `.modelValue` still undefined? Please make sure you're `.value` is of type 'string'.
Now you can enhance your slider by writing custom Validators for it or by
writing a parser to get a custom modelValue type.