Start · Sprachen · JavaScript · Referenz · ElementInternals.validity

ElementInternals.validity

Eigenschaft

Gibt ein schreibgeschütztes <code>ValidityState</code>-Objekt zurück, das den aktuellen Gültigkeitszustand eines formularassoziierten Custom Elements beschreibt.

seit JavaScript Baseline 2023: Chrome 77+, Firefox 98+, Safari 16. Kategorie: webapi

Signatur

get ElementInternals.prototype.validity

Beschreibung

Die Eigenschaft validity von ElementInternals liefert ein ValidityState-Objekt für ein formularassoziiertes Custom Element, also eine Klasse mit static formAssociated = true. Das Objekt enthält dieselben booleschen Merkmale wie bei nativen Formularfeldern: valueMissing, typeMismatch, patternMismatch, tooLong, tooShort, rangeUnderflow, rangeOverflow, stepMismatch, badInput, customError und die Zusammenfassung valid.

Die Eigenschaft selbst ist nur lesbar. Den Zustand setzt du ausschließlich über ElementInternals.setValidity(flags, message, anchor). Wenn du setValidity({}) ohne Merkmale aufrufst, gilt das Element wieder als gültig. Das zurückgegebene Objekt ist „live“ und spiegelt jederzeit den aktuellen Zustand wider.

Typische Einsatzfälle sind Eingabekomponenten wie Datumswähler, Bewertungssterne oder Tag-Eingaben. Sie sollen sich mit form.checkValidity(), :invalid-CSS und der Formularübermittlung genauso verhalten wie ein natives <input>. Oft stellt man validity zusätzlich als öffentlichen Getter der Komponente bereit, damit sie dieselbe Schnittstelle wie native Felder bietet.

Rückgabewert

Typ
ValidityState
Beschreibung
Live-Objekt mit booleschen Gültigkeitsmerkmalen. valid ist true, wenn kein anderes Merkmal gesetzt ist.

Beispiele

Pflichtfeld-Komponente mit Validierung

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

  connectedCallback() {
    this.#update();
  }

  set value(v) {
    this.#value = Number(v);
    this.#internals.setFormValue(String(this.#value));
    this.#update();
  }

  #update() {
    if (this.hasAttribute('required') && this.#value === 0) {
      this.#internals.setValidity({ valueMissing: true }, 'Bitte eine Bewertung wählen.');
    } else {
      this.#internals.setValidity({}); // gültig
    }
  }

  // native API nachbilden
  get validity() { return this.#internals.validity; }
  get validationMessage() { return this.#internals.validationMessage; }
}
customElements.define('rating-input', RatingInput);

const el = document.createElement('rating-input');
el.setAttribute('required', '');
document.body.append(el);
console.log(el.validity.valid, el.validity.valueMissing);
el.value = 4;
console.log(el.validity.valid);
false true true

Fehlerursache auswerten

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

  check(text) {
    if (text.length < 4) {
      this.internals.setValidity({ tooShort: true }, 'Mindestens 4 Zeichen.');
    } else if (!/^[A-Z0-9]+$/.test(text)) {
      this.internals.setValidity({ patternMismatch: true }, 'Nur Großbuchstaben und Ziffern.');
    } else {
      this.internals.setValidity({});
    }
    const v = this.internals.validity;
    return Object.fromEntries(
      ['valid', 'tooShort', 'patternMismatch'].map((k) => [k, v[k]])
    );
  }
}
customElements.define('code-input', CodeInput);

const c = document.createElement('code-input');
console.log(c.check('ab'));
console.log(c.check('abcd'));
console.log(c.check('AB12'));
{ valid: false, tooShort: true, patternMismatch: false } { valid: false, tooShort: false, patternMismatch: true } { valid: true, tooShort: false, patternMismatch: false }

Zusammenspiel mit dem Formular

const form = document.createElement('form');
const rating = document.createElement('rating-input');
rating.setAttribute('required', '');
form.append(rating);
document.body.append(form);

form.addEventListener('submit', (e) => {
  if (!rating.validity.valid) {
    e.preventDefault();
    console.warn(rating.validationMessage);
  }
});

console.log(form.checkValidity()); // berücksichtigt das Custom Element
false

// Wichtig · Fallstricke

  • Ist das Element nicht formularassoziiert (kein static formAssociated = true), löst der Zugriff auf validity eine NotSupportedError-DOMException aus.
  • Die Eigenschaft ist schreibgeschützt. Zuweisungen wie internals.validity.valid = true haben keine Wirkung. Ändern lässt sich der Zustand nur mit setValidity().
  • Setzt du in setValidity() ein Fehlermerkmal, musst du auch einen nicht-leeren message-String übergeben. Sonst wird ein TypeError ausgelöst.
  • Der Browser prüft Attribute wie required oder minlength an Custom Elements nicht automatisch. Diese Prüfung musst du selbst implementieren.
  • Elemente mit disabled, readonly oder innerhalb eines deaktivierten <fieldset> werden von der Constraint-Validierung ausgenommen. validity kann dann trotzdem Fehler melden, obwohl das Formular abgesendet wird.
  • Browser-Unterstützung: Chrome/Edge 77+, Firefox 98+, Safari 16.4+. In älteren Safari-Versionen ist dafür ein Polyfill wie element-internals-polyfill nötig.