Skip to content

[RRFC] FormAssociated mixins #43

@justinfagnani

Description

@justinfagnani
  • I searched for an existing RRFC which might be relevant to my RRFC

Motivation

Building a form associated custom element requires a lot of common boilerplate:

  • Setting static formAssociated = true
  • Attaching ElementInternals
  • Setting a default ARIA role
  • Calling internals.setFormValue() when needed
  • Representing the element's form value and the element state
  • Exposing the value to the element's public API
  • Handling formDisabledCallback()
  • Handling formResetCallback() and formStateRestoreCallback()

Example

A simple-ish FormAssociated() element, with validation, might just forward an input's value to the element's value:

import {FormAssociated, value} from '@lit-labs/form';

class MyFormElement extends FormAssociated(LitElement, {
  role: 'textbox'
}) {

  @formValue()
  accessor value: string = '';
  
  @query()
  accessor #input: HTMLInputElement;

  render() {
    return html`<input .value=${this.value}> @input=${this.#onInput}`;
  }

  #onInput(e) {
    this.value = e.target.value;
  }

  protected _checkValidity() {
    if (this.value.length < 5) {
      return {
        flags: { tooLong: true },
        message: "value is too long",
        anchor: this.#input,
      };
    }
  }
}

In this case the FormAssociated mixin would:

  • set static formAssociated = true
  • set internals.role
  • call setFormValue() when value changes
  • Implements formStateRestoreCallback() to reset the value.

How

A FormAssociated() mixin, paired with @internals, @formValue and @formState decorators.

Current Behavior

Desired Behavior

References

  • n/a

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions