Up to at least Vaadin Flow 23 the official components are Polymer3 (from what I saw), which is basically deprecated in favour of Lit.
Given a server side AbstractSinglePropertyField
(see below for code),
that wraps a simple checkbox and is supposed to "mirror" a property
called checked
from the client.
The server side then listens for checked-changed
events from the
client, which Polymer3 happily fires for such a property.
Now consider the use of a webcomponent using Lit:
import {LitElement, html} from "lit-element";
export class MyCheckBox extends LitElement {
static get properties() {
return {checked: Boolean};
}
render() {
return html`<label><input type="checkbox" ?checked=${this.checked} @click=${this.toggleChecked}/>Toggle</label>`
}
toggleChecked(e) {
this.checked = e.target.checked;
}
}
customElements.define('my-checkbox', MyCheckBox);
Lit no longer automatically fires the checked-changed
event.
So what is the official/easy/... way to deal with client-side property changes and notify the server (which expects "Polymer3-style") about them?
As of now, as a workaround, I fire my own event:
import {LitElement, html} from "lit-element";
export class MyCheckBox extends LitElement {
// ...
update(_changedProperties) {
super.update(_changedProperties);
this.fireChanged(_changedProperties, 'checked'); // XXX
}
fireChanged(_changedProperties, property) {
if (_changedProperties.has(property)) {
let htmlChangedEvent = new CustomEvent(property.concat("-changed"), {
detail: {
propertyName: property,
value: this.html,
oldValue: _changedProperties.get(property),
userOriginated: true
}
});
this.dispatchEvent(htmlChangedEvent);
}
}
}
customElements.define('my-checkbox', MyCheckBox);
The server side (for both client sides):
@Tag('my-checkbox')
@JsModule('./my-checkbox.js')
class MyCheckbox extends AbstractSinglePropertyField<MyCheckbox, Boolean> {
MyCheckbox() {
super('checked', false, false)
}
}
And a trivial test:
@Route("")
class MyForm extends Div {
MyForm() {
def mcb = new MyCheckbox().tap{
addValueChangeListener{
Notification.show("Value changed to ${it.value}")
}
}
add(mcb)
}
}
Without the firing of the "manual" checked-changed
event, the
notification never shows.