Integrating JavaScript Library
You can create custom UI components based on third-party JavaScript libraries. The example in this section demonstrates integration of the jQuery UI Slider widget.
Creating JavaScript Web Component
Create the slider.js
file in the frontend/src/component/slider
folder. It contains a Web Component wrapping the jQuery UI Slider widget. Its ready()
method is used to initialize the widget.
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 | Defines base classes for custom component. |
2 | Defines the name of HTML element. |
3 | Defines custom properties. |
4 | Defines listener on a property change. |
5 | Gets the link to the root element. |
6 | Initializes jQuery UI Slider on the root element. |
7 | Dispatches custom event with the custom-slide-changed name. |
8 | When a property is changed, it sets a new value for the slider. |
9 | Exports custom HTML element with the name defined in the static get is() method. |
Creating Java API for a Web Component
Create the Slider.java
file which is a UI component class. It defines an API for the server code, accessor methods, event listeners, and data sources connection.
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 | Defines the root element that is created automatically by the Component class and can be accessed using the getElement() method. Must be the same as the Web Component exports. |
2 | The @NpmPackage annotation defines an npm package dependency which includes one or more JS modules. |
3 | The @JsModule annotation defines the import of the JavaScript module. |
4 | Adding the @Synchronize annotation to the getter ensures that the browser sends property changes to the server. The annotation defines the name of the DOM event that triggers synchronization, in this case a custom-slide-changed event. |
Handling Events from the Client-side
You can connect a component event to a DOM event that is fired by an element in the browser. To do this, use the @DomEvent
annotation on your event class to specify the name of the DOM event you want to listen to. Vaadin Flow will automatically add a DOM event listener for the element if a component event listener exists.
An event can include additional information, such as the mouse button that was used in a click event. The @DomEvent
constructor supports additional parameters. You can use @EventData
to specify what data to send from the browser.
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 | Using the @DomEvent annotation to connect a Slider component to the custom-slide-changed DOM event. |
2 | Using the @EventData annotation to define additional event data, the slider’s value in this case. |
More information about creating custom components can be found in Vaadin documentation: Importing JavaScript & CSS, Integrating Web Components, Element API. |
Usage Example
After a component is implemented it can be used in views, for example:
@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);
}