2

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.

cfrick
  • 35,203
  • 6
  • 56
  • 68
  • And what is the question? This is how it works as Lit does not have two way data binding like Polymer had. In my components I am firing CustomEvent as well. Minor nitpick, you can use `@property` decorator with Lit instead of `static get properties()` – Tatu Lund Jul 02 '22 at 07:27
  • @TatuLund The question is "what is the official/easy/... way to deal with client-side property changes?" I assumed I am doing it wrong by using a bad hack to make it work. Compared to how it worked previously, this is quite cumbersome. Time to write some utility for that, I guess. – cfrick Jul 02 '22 at 11:07

0 Answers0