> Markdown version of [Binding Data to Custom Components](https://vaadin.com/docs/latest/hilla/lit/guides/forms/web-component-field-strategy). Section index: [llms.txt](https://vaadin.com/docs/latest/hilla/llms.txt)

# Binding Data to Custom Components

While Vaadin components are supported out-of-the-box, the client-side [Form binder](https://vaadin.com/docs/latest/hilla/lit/guides/forms/binder.md) 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 as `required` and `errorMessage`; and

- Create a custom *binder* subclass that associates the new custom field strategy with the custom web component tag.

## <a id="web-component-example"></a>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.

Custom field web component

`my-text-field.ts`

```typescript
@customElement('my-text-field')
export class MyTextField extends LitElement {
  @property({ type: String }) label = '';
  @property({ type: String }) value = '';

  // custom properties that do not work with the default Binder
  @property({ type: Boolean }) mandatory = false;
  @property({ type: Boolean }) hasError = false;
  @property({ type: String }) error = '';

  // ...
}
```

## <a id="defining-a-field-strategy"></a>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:

Example field strategy

`my-text-field-strategy.ts`

```typescript
import type { FieldStrategy } from '@vaadin/hilla-lit-form';
import type { MyTextField } from './my-text-field';

export class MyTextFieldStrategy implements FieldStrategy {
  element: MyTextField;

  constructor(element: MyTextField) {
    this.element = element;
  }

  set required(required: boolean) {
    this.element.mandatory = required;
  }

  set invalid(invalid: boolean) {
    this.element.hasError = invalid;
  }

  set errorMessage(errorMessage: string) {
    this.element.error = errorMessage;
  }

  // ...
}
```

## <a id="using-a-field-strategy"></a>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.

Using a Custom Field Strategy in Binder

`my-binder.ts`

```typescript
import type {
  FieldStrategy,
  ProvisionalModel,
  ProvisionalModelConstructor,
} 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 ProvisionalModel> extends Binder<M> {
  constructor(context: Element, model: ProvisionalModelConstructor<M>) {
    super(context, model);
  }

  override getFieldStrategy(element: any, model?: ProvisionalModel): FieldStrategy {
    if (element.localName === 'my-text-field' && model instanceof StringModel) {
      return new MyTextFieldStrategy(element);
    }
    return super.getFieldStrategy(element);
  }
}
```

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.

Using a Field Web Component in a Form

`my-form.ts`

```typescript
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>
    `;
  }
  // ...
}
```
