Start · Sprachen · JavaScript · Referenz · ElementInternals.setFormValue()

ElementInternals.setFormValue()

Methode

Legt den Wert fest, den ein formularassoziiertes Custom Element beim Absenden übermittelt, und optional einen internen Zustand für die Wiederherstellung.

seit JavaScript Baseline 2023: Chrome 77+, Edge 79+, Firefox 98+, Kategorie: webapi

Signatur

ElementInternals.prototype.setFormValue(value, state)

Beschreibung

Mit setFormValue() teilt ein formularassoziiertes Custom Element (also eine Klasse mit static formAssociated = true) dem Browser mit, welchen Wert es beim Absenden eines <form> beisteuert. Ohne diesen Aufruf taucht das Element weder in FormData noch in der HTTP-Anfrage auf, auch wenn es ein name-Attribut hat.

Der erste Parameter value ist der Übermittlungswert. Ein String oder eine File wird unter dem name-Attribut des Elements übermittelt. Mit einem FormData-Objekt kann ein einzelnes Element auch mehrere Name-Wert-Paare beisteuern, zum Beispiel ein Datumsbereich mit start und end. Bei null übermittelt das Element nichts.

Der optionale zweite Parameter state ist der Zustand. Er wird nicht übermittelt, sondern nur vom Browser gespeichert: beim Wiederherstellen einer Sitzung, beim Zurück-Navigieren oder beim automatischen Ausfüllen. Dann bekommt das Element den Zustand über den Callback formStateRestoreCallback(state, mode) zurück. Das ist nützlich, wenn sich die interne Darstellung vom übermittelten Wert unterscheidet, zum Beispiel wenn der Nutzer „15.03.2024“ eingibt, übermittelt aber „2024-03-15“ wird.

Rufe setFormValue() jedes Mal auf, wenn sich der Wert ändert, meist in Event-Handlern für input oder change und im Setter einer value-Eigenschaft. Setze außerdem in formResetCallback() den Anfangswert erneut.

Parameter

Name Typ Default Beschreibung
$value Pflicht string | File | FormData | null Übermittlungswert. Ein String oder eine File wird unter dem name-Attribut des Elements übermittelt. Ein FormData-Objekt steuert alle enthaltenen Einträge unter ihren eigenen Namen bei. Bei null übermittelt das Element keinen Wert.
$state string | File | FormData | null gleich value Interner Zustand für die Wiederherstellung durch den Browser (Sitzung, Zurück-Navigation, automatisches Ausfüllen). Er wird nicht übermittelt und kommt über formStateRestoreCallback() zurück. Fehlt er, wird value als Zustand verwendet.

Rückgabewert

Typ
void
Beschreibung
Kein Rückgabewert (undefined).

Beispiele

Einfaches formularassoziiertes Eingabeelement

class RatingInput extends HTMLElement {
  static formAssociated = true;
  #internals;
  #value = 0;

  constructor() {
    super();
    this.#internals = this.attachInternals();
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.innerHTML = [1, 2, 3, 4, 5]
      .map((n) => `<button type="button" data-v="${n}">★</button>`)
      .join('');
    shadow.addEventListener('click', (e) => {
      const v = e.target.dataset?.v;
      if (v) this.value = Number(v);
    });
  }

  get value() { return this.#value; }
  set value(v) {
    this.#value = v;
    // Wert an das Formular melden
    this.#internals.setFormValue(String(v));
  }

  formResetCallback() {
    this.value = 0;
  }
}
customElements.define('rating-input', RatingInput);

// HTML: <form id="f"><rating-input name="sterne"></rating-input></form>
const form = document.querySelector('#f');
document.querySelector('rating-input').value = 4;
console.log(new FormData(form).get('sterne'));
4

Mehrere Werte über FormData übermitteln

class DateRange extends HTMLElement {
  static formAssociated = true;
  #internals = this.attachInternals();

  setRange(start, end) {
    const data = new FormData();
    data.append('start', start);
    data.append('end', end);
    // Ein Element, zwei Formularfelder
    this.#internals.setFormValue(data);
  }
}
customElements.define('date-range', DateRange);

// HTML: <form id="buchung"><date-range></date-range></form>
document.querySelector('date-range').setRange('2024-07-01', '2024-07-14');
const fd = new FormData(document.querySelector('#buchung'));
console.log([...fd.entries()]);
[["start", "2024-07-01"], ["end", "2024-07-14"]]

Wert und Zustand trennen und wiederherstellen

class GermanDateInput extends HTMLElement {
  static formAssociated = true;
  #internals = this.attachInternals();
  #input;

  connectedCallback() {
    this.#input = document.createElement('input');
    this.#input.placeholder = 'TT.MM.JJJJ';
    this.append(this.#input);
    this.#input.addEventListener('input', () => this.#sync());
  }

  #sync() {
    const raw = this.#input.value; // z. B. "15.03.2024"
    const m = raw.match(/^(\d{2})\.(\d{2})\.(\d{4})$/);
    const iso = m ? `${m[3]}-${m[2]}-${m[1]}` : null;
    // Übermittelt wird ISO, gespeichert die Eingabe des Nutzers
    this.#internals.setFormValue(iso, raw);
  }

  formStateRestoreCallback(state, mode) {
    // mode: 'restore' oder 'autocomplete'
    this.#input.value = state ?? '';
    this.#sync();
  }
}
customElements.define('german-date', GermanDateInput);

// Wichtig · Fallstricke

  • Nur für formularassoziierte Elemente: Ohne static formAssociated = true wirft der Aufruf eine NotSupportedError-DOMException. Das gilt auch für attachInternals() und den Zugriff auf formularbezogene Eigenschaften.
  • Das name-Attribut fehlt: Bei einem String oder einer File wird ohne name-Attribut nichts übermittelt. Bei FormData ist das name-Attribut egal, weil jeder Eintrag seinen eigenen Namen hat.
  • FormData wird kopiert: Spätere Änderungen am übergebenen Objekt wirken sich nicht aus. Bei jeder Änderung muss setFormValue() erneut aufgerufen werden.
  • Deaktivierte Elemente: Ist das Element über disabled oder ein deaktiviertes <fieldset> deaktiviert, wird sein Wert trotz setFormValue() nicht übermittelt.
  • Validierung ist getrennt: setFormValue() prüft den Wert nicht. Für Pflichtfelder und Fehlermeldungen brauchst du ElementInternals.setValidity().
  • Kompatibilität: Chromium unterstützt die Methode seit Version 77, Firefox seit 98 und Safari erst seit 16.4. Für ältere Safari-Versionen gibt es ein Polyfill (element-internals-polyfill). Prüfen kannst du die Unterstützung mit 'setFormValue' in ElementInternals.prototype.
  • Unterstützung des Zustands-Callbacks: Wie zuverlässig formStateRestoreCallback aufgerufen wird, unterscheidet sich je nach Browser, besonders beim automatischen Ausfüllen. Verlass dich daher nicht allein darauf.