> Markdown version of [Creating a Component that Has a Value](https://vaadin.com/docs/latest/flow/binding-data/field). Section index: [llms.txt](https://vaadin.com/docs/latest/flow/llms.txt)

# Creating a Component that Has a Value

The basic property of a field component is that it has a value, which the user can edit. To express that, a field must implement the `HasValue` interface. This is a requirement in order for a component to work with `Binder`.

The `HasValue` interface defines:

- methods to access the value itself;

- an event when the value changes;

- helpers to deal with empty values;

- a `ReadOnly` mode;

- a `required` indicator.

## <a id="helper-classes"></a>Helper Classes

You can use the following classes as a base class for custom fields:

- `AbstractField` is the most basic, but also the most flexible base class. It has many details that you need to take care of, but it supports complex use cases.

- `AbstractCompositeField` is similar to `AbstractField`, except that it uses `Composite` instead of `Component` as the base class. It’s suitable when the value input component consists of several individual components.

- `AbstractSinglePropertyField` is suitable when the value is the property of the single element of the component. This base class simplifies a common use case found in many Web Components that are similar in design to the native `<input>` element.

## <a id="using-a-single-element-property-as-the-value"></a>Using a Single-element Property as the Value

Many components extend Web Components that have a property that contains the component’s value. The property name is typically `value`, and it fires a `value-changed` event when changed.

When the property type is a string, number, or Boolean, all you need to do is to extend `AbstractSinglePropertyField` and call its constructor with the name of the property, the default value, and whether it allows null values.

The `paper-slider` Web Component is a compliant example. It has an integer property named `value`, it displays the slider at the 0 position if the value isn’t set, and doesn’t support showing no value at all.

For example, consider a `PaperSlider` component that extends `AbstractSinglePropertyField`:

```java
@Tag("paper-slider")
@NpmPackage(value = "@polymer/paper-slider",
            version = "3.0.1")
@JsModule("@polymer/paper-slider/paper-slider.js")
public class PaperSlider
        extends AbstractSinglePropertyField<PaperSlider,
            Integer> {
    public PaperSlider() {
        super("value", 0, false);
    }
}
```

- The type parameters of `AbstractSinglePropertyField` are:

  - The type of the `getSource()` method in fired value-change events (`PaperSlider`).

  - The value type (`Integer`).

- The default value of `0` is automatically used by the `clear()` and `isEmpty()` methods. `clear()` sets the field value to the default value, and `isEmpty()` returns `true` if the field value is the default value.

> **Note: Vaadin Uses Polymer 3**
>
> Vaadin uses [Polymer 3](https://polymer-library.polymer-project.org/3.0/docs/about_30). This version provides the best compatibility for integrating third-party Web Components.

### <a id="converting-property-values"></a>Converting Property Values

With some Web Components, there is a Java type that’s more suitable than the type of the element property.

It’s possible to configure `AbstractSinglePropertyField` to apply a converter when changing, reading, or writing the value to the element property.

For example, the `value` property of `<input type="date">` is an ISO 8601-formatted string (`YYYY-MM-DD`). You can convert this into a `DatePicker` component to select a `LocalDate`.

**Example**: `DatePicker` component that allows the selection of a `LocalDate`. It extends `AbstractSinglePropertyField` and provides a callback to convert from `LocalDate` to `String`, and a callback in the opposite direction.

```java
@Tag("input")
public class DatePicker
        extends AbstractSinglePropertyField<DatePicker,
            LocalDate> {

    public DatePicker() {
        super("value", null, String.class,
                LocalDate::parse,
                LocalDate::toString);

        getElement().setAttribute("type", "date");

        setSynchronizedEvent("change");
    }

    @Override
    protected boolean hasValidValue() {
        return isValidDateString(getElement()
                .getProperty("value"));
    }
}
```

In this scenario, the convention of listening for an event named `<propertyName>-changed` is inappropriate. Instead, the `setSynchronizedEvent("change")` call overrides the default configuration, and listens for the change event in the browser.

Overriding the `hasValidValue()` method validates the element value before it gets passed to the `LocalDate.parse()` method that’s defined in the constructor. In this way, invalid values are ignored, instead of causing exceptions.

## <a id="combining-properties-into-one-value"></a>Combining Properties into One Value

`AbstractSinglePropertyField` works with Web Components that have the value in a single-element property. In other cases, the value of a component can be a composition of properties in one or more elements. In such cases, the best solution is often to extend `AbstractField`.

When you extend `AbstractField`, there are two different value representations to handle:

- **Presentation value**

  The value displayed to the user in the browser, for example as element properties.

- **Model value**

  The value available through the `getValue()` method.

The field needs to keep the two values in sync, unless:

- the value is being changed, or

- the element properties are in an invalid state that can’t, or shouldn’t, be represented through `getValue()`.

For example, consider a `simple-date-picker` Web Component that has separate integer properties for the selected date: `year`, `month` and `dayOfMonth`. For each property, there is a corresponding event when the user makes a change: `year-changed`, `month-changed`, and `day-of-month-changed`.

Start by implementing a `SimpleDatePicker` component that extends `AbstractField` and passes the default value to its constructor.

```java
@Tag("simple-date-picker")
public class SimpleDatePicker
    extends AbstractField<SimpleDatePicker, LocalDate> {

    public SimpleDatePicker() {
        super(null);
    }
}
```

> **Note:** The type parameters are the same as for `AbstractSinglePropertyField`: the `getSource()` type for the value-change event and the value type.

When you call `setValue(T value)` with a new value, `AbstractField` invokes the `setPresentationValue(T value)` method with the new value.

You need to implement the `setPresentationValue(T value)` method so that the component updates the element properties to match the values set:

```java
@Override
protected void setPresentationValue(LocalDate value) {
    Element element = getElement();

    if (value == null) {
        element.removeProperty("year");
        element.removeProperty("month");
        element.removeProperty("dayOfMonth");
    } else {
        element.setProperty("year", value.getYear());
        element.setProperty("month",
                value.getMonthValue());
        element.setProperty("dayOfMonth",
                value.getDayOfMonth());
    }
}
```

To handle value changes coming from the browser, the component must listen to appropriate internal events and pass a new value to the `setModelValue(T value, boolean fromClient)` method. `AbstractField` uses this to check whether the provided value has actually changed and, if it has, it fires a value-change event to all listeners.

You need to update the constructor to define each of the element properties as synchronized, and add the same property-change listener to each of them:

```java
public SimpleDatePicker() {
    super(null);

    setupProperty("year", "year-changed");
    setupProperty("month", "month-changed");
    setupProperty("dayOfMonth", "dayOfMonth-changed");
}

private void setupProperty(String name, String event) {
    Element element = getElement();

    element.addPropertyChangeListener(name, event,
            this::propertyUpdated);
}
```

> **Tip:** By default, `AbstractField` calls `Objects.equals()` to determine whether a new value is the same as the previous value. If the `equals()` method of the value type isn’t appropriate, you can override the `valueEquals()` method to implement your own comparison logic.

> **Warning: Use AbstractField only with immutable-value instances**
>
> `AbstractField` should only be used with immutable-value instances. No value-change event is fired if the original `getValue()` instance is modified and passed to `setModelValue()` or `setValue()`.

The final step is to implement the property-change listener to create a new `LocalDate` based on the element property values, and pass it to `setModelValue()`.

```java
private void propertyUpdated(
        PropertyChangeEvent event) {
    Element element = getElement();

    int year = element.getProperty("year", -1);
    int month = element.getProperty("month", -1);
    int dayOfMonth = element.getProperty(
            "dayOfMonth", -1);

    if (year != -1 && month != -1 && dayOfMonth != -1) {
        LocalDate value = LocalDate.of(
                year, month, dayOfMonth);
        setModelValue(value, event.isUserOriginated());
    }
}
```

If any of the properties aren’t filled in, `setModelValue()` isn’t called. This means that `getValue()` returns the same value it returned the previous time it was called.

The component can call `setModelValue()` from inside its `setPresentationValue()` implementation. In this case, the call sets the value of the component to the value passed to `setModelValue()`. This value is used instead of the original value. This is useful to transform provided values, for example to make all strings uppercase.

If you have a percentage field whose value can only be in the range 0 to 100, for example, you can use:

```java
@Override
protected void setPresentationValue(Integer value) {
        if (value < 0) value = 0;
        if (value > 100) value = 100;

        getElement().setProperty("value", value);
}
```

If the value set from the server is, for example, 138, the following code sets the value to 100 on the client, but the internal server value remains 138:

```java
@Override
protected void setPresentationValue(Integer value) {
        if (value < 0) value = 0;
        if (value > 100) value = 100;

        getElement().setProperty("value", value);
        setModelValue(value, false);
}
```

Calling `setModelValue()` from the `setPresentationValue()` implementation doesn’t fire a value-change event.

If `setModelValue()` is called multiple times, the value of the last invocation is used, and there is no need to worry about causing infinite loops.

## <a id="creating-fields-from-other-fields"></a>Creating Fields from Other Fields

`AbstractCompositeField` makes it possible to create a field component that has a value based on the value of one or more internal fields.

For example, consider an employee selector field that allows the user first to select a department from a combo box, and then to select an employee from that department in another combo box. The component itself is a `Composite`, based on a `HorizontalLayout` that contains the two `ComboBox` components, displayed side by side.

> **Tip:** Another use case for `AbstractCompositeField` is to create a field component that’s based directly on another field, while converting the value from that field.

The class declaration is a mix of `Composite` and `AbstractField`.

1. The first type parameter defines the `Composite` content type, the second is for the value-change event `getSource()` type, and the third is the `getValue()` type of the field.

2. Initialize instance fields for each `ComboBox`.

```java
public class EmployeeField extends
        AbstractCompositeField<HorizontalLayout,
            EmployeeField, Employee> {
    private ComboBox<Department> departmentSelect =
            new ComboBox<>("Department");
    private ComboBox<Employee> employeeSelect =
            new ComboBox<>("Employee");
}
```

In the constructor:

1. Configure `departmentSelect()` value changes to update the items in `employeeSelect()`.

2. The constructor sets the employee selected in `employeeSelect()` as the field’s value.

3. Both combo boxes are added to the horizontal layout.

```java
public EmployeeField() {
    super(null);

    departmentSelect.setItems(
            EmployeeService.getDepartments());

    departmentSelect.addValueChangeListener(event -> {
        Department department = event.getValue();

        employeeSelect.setItems(EmployeeService
                .getEmployees(department));
        employeeSelect.setEnabled(department != null);
    });

    employeeSelect.addValueChangeListener(event ->
            setModelValue(event.getValue(), true));

    getContent().add(departmentSelect, employeeSelect);
}
```

As a next step, implement `setPresentationValue()` to update the combo boxes according to a specified employee.

```java
@Override
protected void setPresentationValue(Employee employee) {
    if (employee == null) {
        departmentSelect.clear();
    } else {
        departmentSelect.setValue(
                employee.getDepartment());
        employeeSelect.setValue(employee);
    }
}
```

You can change how the required indicator is displayed for the field.

The implementation that follows assumes that the component’s root element reacts to a property with name `required`, which works well with Web Components that mimic the API of the `<input>` element. In this example, the required indicator is displayed for the employee combo box.

```java
@Override
public void setRequiredIndicatorVisible(
        boolean required) {
   employeeSelect.setRequiredIndicatorVisible(required);
}

@Override
public boolean isRequiredIndicatorVisible() {
    return employeeSelect.isRequiredIndicatorVisible();
}
```

You need to handle the `readonly` property by marking both combo boxes as read-only. The following implementation is similar to how `required` indicators are handled in the previous example, except that it uses the `readonly` property.

```java
@Override
public void setReadOnly(boolean readOnly) {
    departmentSelect.setReadOnly(readOnly);
    employeeSelect.setReadOnly(readOnly);
}

@Override
public boolean isReadOnly() {
    return employeeSelect.isReadOnly();
}
```

`4F463F71-4C2A-480C-A507-AC5D8F39B46D`
