Интеграция JavaScript-библиотеки
Собственные компоненты пользовательского интерфейса можно создавать на основе сторонних JavaScript-библиотек. Пример в данном разделе демонстрирует интеграцию виджета jQuery UI Slider.
Создание JavaScript веб-компонента
Создайте файл slider.js в папке frontend/src/component/slider. Он содержит веб-компонент, оборачивающий виджет jQuery UI Slider. Его метод ready() используется для инициализации виджета.
import 'jquery/jquery.js'
import 'jquery-ui/dist/jquery-ui.js'
import {PolymerElement} from '@polymer/polymer/polymer-element.js';
import {defineCustomElement} from '@vaadin/component-base/src/define.js';
import {ElementMixin} from '@vaadin/component-base/src/element-mixin.js';
class Slider extends ElementMixin(PolymerElement) { (1)
    static get is() {
        return 'demo-slider'; (2)
    }
    static get properties() { (3)
        return {
            min: {
                type: Number,
                value: 0,
                observer: '_onMinChange' (4)
            },
            max: {
                type: Number,
                value: 100,
                observer: '_onMaxChange'
            },
            value: {
                type: Number,
                notify: true,
                observer: '_onValueChange'
            },
            /** @private */
            _slider: {
                type: Object
            }
        }
    }
    ready() {
        super.ready();
        this._slider = $(this); (5)
        this._slider.slider({ (6)
            min: this.min,
            max: this.max,
            change: function (event, ui) {
                if (this.value === ui.value) {
                    return;
                }
                this.value = ui.value;
                const slideChangeEvent = new CustomEvent(
                    'custom-slide-changed',
                    {detail: {value: ui.value}}
                );
                this.dispatchEvent(slideChangeEvent); (7)
            }
        });
    }
    /**
     * @protected
     */
    _onValueChange(value) { (8)
        if (this._slider === undefined) {
            return;
        }
        this._slider.slider("value", value);
    }
    /**
     * @protected
     */
    _onMinChange(value) {
        if (this._slider === undefined) {
            return;
        }
        this._slider.slider("option", "min", value);
    }
    /**
     * @protected
     */
    _onMaxChange(value) {
        if (this._slider === undefined) {
            return;
        }
        this._slider.slider("option", "max", value);
    }
}
defineCustomElement(Slider); (9)
export {Slider};| 1 | Определяет базовые классы для пользовательского компонента. | 
| 2 | Определяет имя HTML-элемента. | 
| 3 | Определяет пользовательские свойства. | 
| 4 | Определяет слушатель изменения свойства. | 
| 5 | Получает ссылку на корневой элемент. | 
| 6 | Инициализирует jQuery UI Slider на корневом элементе. | 
| 7 | Генерирует пользовательское событие с именем custom-slide-changed. | 
| 8 | Когда свойство изменяется, устанавливает новое значение для слайдера. | 
| 9 | Экспортирует пользовательский HTML-элемент с именем, определенным в методе static get is(). | 
Создание Java API для веб-компонента
Создайте файл Slider.java, который является классом пользовательского интерфейса. Он определяет API для серверного кода, методы доступа, слушатели событий и соединение с источниками данных.
import com.vaadin.flow.component.*;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.shared.Registration;
@Tag("demo-slider") (1)
@NpmPackage(value = "jquery", version = "1.9.1") (2)
@NpmPackage(value = "jquery-ui", version = "1.13.2")
@CssImport("jquery-ui/dist/themes/base/jquery-ui.css")
@JsModule("./src/component/slider/slider.js") (3)
public class Slider extends Component implements HasSize {
    private static final String VALUE_PROPERTY = "value";
    private static final String MIN_PROPERTY = "min";
    private static final String MAX_PROPERTY = "max";
    public Slider() {
    }
    public int getMin() {
        return getElement().getProperty(MIN_PROPERTY, 0);
    }
    public void setMin(int min) {
        getElement().setProperty(MIN_PROPERTY, min);
    }
    public int getMax() {
        return getElement().getProperty(MAX_PROPERTY, 100);
    }
    public void setMax(int max) {
        getElement().setProperty(MAX_PROPERTY, max);
    }
    @Synchronize("custom-slide-changed") (4)
    public int getValue() {
        return getElement().getProperty(VALUE_PROPERTY, 0);
    }
    public void setValue(int value) {
        getElement().setProperty(VALUE_PROPERTY, value);
    }
}| 1 | Определяет корневой элемент, который создается автоматически классом Componentи доступен с помощью методаgetElement(). Должен совпадать с экспортами веб-компонента. | 
| 2 | Аннотация @NpmPackageопределяет зависимость от npm-пакета, который включает один или несколько JS-модулей. | 
| 3 | Аннотация @JsModuleопределяет импорт модуля JavaScript. | 
| 4 | Добавление аннотации @Synchronizeк геттеру гарантирует, что браузер отправляет изменения свойств на сервер. Аннотация определяет имя DOM-события, которое инициирует синхронизацию, в данном случае событиеcustom-slide-changed. | 
Обработка событий на стороне клиента
Событие компонента можно подключить к DOM-событию, которое вызывается элементом в браузере. Для этого используется аннотация @DomEvent в классе события, которая указывает имя DOM-события, на которое необходимо подписаться. Vaadin Flow автоматически добавит слушатель DOM-событий для элемента, если существует слушатель событий компонента.
Событие может включать дополнительную информацию, такую как кнопка мыши, использованная в событии клика. Конструктор @DomEvent поддерживает дополнительные параметры. Вы можете использовать @EventData, чтобы указать, какие данные отправить из браузера.
public Registration addValueChangeListener(ComponentEventListener<SlideChangedEvent> listener) {
    return addListener(SlideChangedEvent.class, listener);
}
@DomEvent("custom-slide-changed") (1)
public static class SlideChangedEvent extends ComponentEvent<Slider> {
    protected int value;
    public SlideChangedEvent(Slider source, boolean fromClient,
                             @EventData("event.detail.value") int value) { (2)
        super(source, fromClient);
        this.value = value;
    }
    public int getValue() {
        return value;
    }
}| 1 | Использование аннотации @DomEventдля подключения компонента Slider к DOM-событиюcustom-slide-changed. | 
| 2 | Использование аннотации @EventDataдля определения дополнительных данных события, в данном случае значения слайдера. | 
| Более подробную информацию о создании пользовательских компонентов можно найти в документации Vaadin: Импорт JavaScript и CSS, Интеграция веб-компонентов, API элементов. | 
Пример использования
После реализации компонента его можно использовать в экранах, например:
@Autowired
protected Notifications notifications;
@Subscribe
public void onInit(final InitEvent event) {
    Slider slider = new Slider();
    slider.setWidth("20em");
    slider.setMin(10);
    slider.setMax(100);
    slider.addValueChangeListener(changedEvent ->
            notifications.create("New value is : " + changedEvent.getValue())
                    .withPosition(Notification.Position.MIDDLE)
                    .show());
    getContent().add(slider);
}