Binding Data to Custom Components
While Vaadin components are supported out-of-the-box, the client-side Form binder can be configured to support any web component. This article explains how to create a form with a custom <my-text-field>
web component.
Using a custom web component in a form requires two steps:
-
Create a field strategy that tells the form binder how to get and set the component
value
and other properties, such asrequired
anderrorMessage
; and -
Create a custom binder subclass that associates the new custom field strategy with the custom web component tag.
Web Component Example
Consider the following LitElement component for use in form binding. It doesn’t expose properties such as required
, invalid
and errorMessage
. This is why the default field strategy that works for all Vaadin components would not work here.
Source code
Custom field web component
Defining a Field Strategy
The first step towards using a web component as a field is to define a field strategy. You need to implement the FieldStrategy
interface, as in the following example:
Source code
Example field strategy
Using a Field Strategy
The second step in using a custom web component is to make the Binder class a subclass and override the getFieldStrategy(element)
method to use a custom field strategy for any my-text-field
components it finds in a form. This method receives as arguments the element which is mapped to the component and the model, which can in turn affect the binding strategy. For example, the Combo Box
component has specialized support for objects and arrays.
Source code
Using a Custom Field Strategy in Binder
import type {
AbstractModel,
DetachedModelConstructor,
FieldStrategy,
} from '@vaadin/hilla-lit-form';
import { Binder, StringModel } from '@vaadin/hilla-lit-form';
import { MyTextFieldStrategy } from './my-text-field-strategy';
export class MyBinder<M extends AbstractModel> extends Binder<M> {
constructor(context: Element, model: DetachedModelConstructor<M>) {
super(context, model);
}
override getFieldStrategy(element: any, model?: AbstractModel): FieldStrategy {
if (element.localName === 'my-text-field' && model instanceof StringModel) {
return new MyTextFieldStrategy(element);
}
return super.getFieldStrategy(element);
}
}
Using a Custom Field Strategy in Binder
You can now use my-text-field
components in a form, provided that you use the extended MyBinder
class to handle data binding in that form.
Source code
Using a Field Web Component in a Form
import './my-text-field';
import { html, LitElement } from 'lit';
import { customElement } from 'lit/decorators.js';
import { field } from '@vaadin/hilla-lit-form';
import SamplePersonModel from 'Frontend/generated/com/vaadin/demo/fusion/forms/fieldstrategy/SamplePersonModel';
import { MyBinder } from './my-binder';
@customElement('person-form-view')
export class PersonFormViewElement extends LitElement {
private binder = new MyBinder(this, SamplePersonModel);
render() {
return html`
<h3>Personal information</h3>
<vaadin-form-layout>
<my-text-field
label="First name"
...="${field(this.binder.model.firstName)}"
></my-text-field>
</vaadin-form-layout>
`;
}
// ...
}