Zum Inhalt
r/ rittek uiDOCS

OPTIONALES MODUL · FORMULARE

Viele Möglichkeiten. Eine klare Auswahl.

Suchbare Mehrfachauswahl mit entfernbaren Chips, Tastaturbedienung und einem nativen Formularfeld als Grundlage.

Projektkompetenzen auswählen

Mindestens eine, höchstens drei Kompetenzen. Die Suche nach „Asthetik“ findet auch „Ästhetik“. Dieses Beispiel zeigt Formulardaten nur lokal an.

Noch keine Änderungen.

1. Ein normales HTML-Formular erweitern

Ohne JavaScript bleibt das native Mehrfachfeld benutzbar. Über name="skills[]" erhält PHP ein Array in $_POST['skills']. Die Moduldatei und ihre Modelldatei müssen zusammen im selben Ordner liegen.

HTML
<link rel="stylesheet" href="/assets/rittek.css">
<link rel="stylesheet" href="/assets/multiselect.css">
<form action="/save.php" method="post">
  <label for="my-skills">Kompetenzen</label>
  <select id="my-skills" name="skills[]" multiple required
          data-r-multiselect data-r-max-selected="3">
    <option value="html">HTML</option>
    <option value="php">PHP</option>
    <option value="design">Design</option>
  </select>
  <button type="submit">Speichern</button>
  <button type="reset">Zurücksetzen</button>
</form>
<script type="module">
  import {initMultiSelect} from '/assets/modules/multiselect.js';
  const selection = initMultiSelect(document);
</script>

2. Eigene Logik und Grenzen

data-r-min-selected und data-r-max-selected setzen Grenzen. Alternativ gelten minSelected und maxSelected in der Initialisierung. Das originale required erzwingt immer mindestens einen Eintrag. Initialisiere die Mehrfachauswahl vor initForms(), falls du das optionale Formularmodul zusätzlich verwendest.

JavaScript
import {createMultiSelect} from '/assets/modules/multiselect.js';

const field = document.querySelector('#my-skills');
const control = createMultiSelect(field, {
  minSelected: 1,
  maxSelected: 3
});
console.log(control.getValues()); // Aktuelle übermittelbare Werte

// Auswahl programmatisch über das native Feld ändern:
field.options[0].selected = true;
field.dispatchEvent(new Event('change', {bubbles: true}));

control.refresh({maxSelected: 2});
// control.destroy(); // Native Ansicht, Attribute und Labels wiederherstellen

field.parentElement.addEventListener('rittek:multiselectchange', event => {
  console.log(event.detail.values, event.detail.source);
});

Verhalten & Formularvertrag

  • Suche filtert nur die Liste; bereits gewählte Chips bleiben erhalten. Pfeil hoch/runter navigiert, Home/End springt im geöffneten Menü, Enter schaltet einen Eintrag, Escape schließt. Backspace bei leerer Suche entfernt den letzten entfernbaren Chip in der Reihenfolge des nativen Feldes.
  • „Treffer auswählen“ ergänzt sichtbare verfügbare Einträge bis zum Maximum. „Auswahl leeren“ entfernt verfügbare gewählte Einträge. Deaktivierte gewählte Optionen bleiben gesperrt und werden entsprechend gekennzeichnet.
  • Die Auswahl steht immer in option.selected. FormData und normale PHP-Formulare verwenden die nativen Werte. Deaktivierte Optionen, deaktivierte Optionsgruppen und ein deaktiviertes Feld werden nach HTML-Regeln nicht übermittelt; getValues() berücksichtigt das ebenfalls. Doppelte Werte bleiben möglich, wenn die nativen Optionen gleiche Werte haben.
  • Das versteckte native Feld behält name und form. Seine Pflichtvalidierung übernimmt das sichtbare Suchfeld über customValidity; es erhält keinen Namen und übermittelt keinen Suchtext. Formularvalidierung kann diesen sichtbaren Fokuspunkt erreichen. Minimum/Maximum werden auch bei vorhandener Überbelegung geprüft, aber vorhandene Werte werden nicht heimlich gelöscht. Serverprüfung bleibt erforderlich.
  • Reset stellt defaultSelected wieder her. Änderungen an disabled, Optionsstruktur und Text werden automatisch beobachtet; nach programmatischen selected-Eigenschaftsänderungen ein natives change auslösen oder refresh() aufrufen. Wird das Feld in ein anderes Formular oder Fieldset verschoben, destroy() und neu initialisieren. refresh() nach destroy() wirft bewusst einen Fehler.
  • Mehrfaches Initialisieren ersetzt die vorherige Instanz ohne doppelte Oberfläche. destroy() erhält die aktuelle native Auswahl, stellt required und Labelzuordnung wieder her und überträgt gegebenenfalls den Fokus zurück. Daten bleiben lokal; das Modul sendet und speichert nichts.