async event handlers in lit-html

531 views Asked by At

Is there a way to have async event handlers in lit-html ?

I have this submit event that's being triggered when the form is submitted to create a new user, but I also want to reload the list of users after a new user is added.

    constructor(container: Element, state: app.state.DashboardState) {
        this.container = container;
        this.state = state;

        this.state.usersCreateState.changed = () => render(html`
            <form
                @submit="${e => this.submit(e)}"
                class="stack display:flex flex-grow:1">

In order to do that, I need to await the usersCreate before I can refresh the user list.

    async submit(e) {
        e.preventDefault();
        document.querySelector(":focus")?.dispatchEvent(new Event("blur"))
        await this.state.usersCreateState.create.submit()
        this.state.usersListState.list.submit()
    }

When making the submit(e) async, the submit event no longer triggers meaning the preventDefault doesn't trigger and instead, it tries to POST to the current URL while dumping this error in the console:

VM4535 user.ecff3a6d.js:20420 Uncaught ReferenceError: regeneratorRuntime is not defined
    at UsersCreate.submit (VM4535 user.ecff3a6d.js:20420)
    at HTMLFormElement.<anonymous> (VM4535 user.ecff3a6d.js:20408)
    at EventPart.handleEvent (VM4535 user.ecff3a6d.js:19355)
    at HTMLFormElement.EventPart.__boundHandleEvent (VM4535 user.ecff3a6d.js:19317)
submit @ VM4535 user.ecff3a6d.js:20420
(anonymous) @ VM4535 user.ecff3a6d.js:20408
handleEvent @ VM4535 user.ecff3a6d.js:19355
EventPart.__boundHandleEvent @ VM4535 user.ecff3a6d.js:19317

If I remove the async and await, this submit event triggers perfectly, except that the usersList reloads before or after the userCreate completed

The ...create.submit() / ...list.submit() methods are defined in Kotlin

    @JsName("submit")
    fun submit(): Promise<ResultVO> {

which generates TypeScript containing kotlin.js.Promise

submit(): kotlin.js.Promise<io.jvaas.state.vo.ResultVO>;

which is just a regular JavaScript Promise:

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.js/-promise/

Is there a way to get lit-html to correctly use the async event handler?

Alternatively, I could just do a callback, but the async / await just looks much better

    submit(e) {
        e.preventDefault();
        document.querySelector(":focus")?.dispatchEvent(new Event("blur"));
        this.state.usersCreateState.create.submit().then(() => {
            this.state.usersListState.list.submit();
        })
    }
1

There are 1 answers

1
Justin Fagnani On

Your problem doesn't seem to have anything to do with the event handlers. It looks like you're compiling to an old JS language version - at least pre ES2017 which added async functions (async/await) - and you're not loading the library (Regenerator Runtime) required to run the transformed async functions.

You need to load Regenerator: https://www.npmjs.com/package/regenerator-runtime

If you're using Babel to compile, this option might help: https://babeljs.io/docs/en/babel-plugin-transform-runtime#regenerator-aliasing