Bei dem Open Source Widget „react-select“ handelt es sich um ein von uns entwickeltes, durchsuchbares Dropdown-Menü inklusive asynchroner Datenabfrage.
Da in vielen Fällen das von HTML 5 bereitgestellte Dropdown nicht ausreicht, haben wir ein eigenes Select für das von uns oft verwendete Framework React entwickelt. Der Fokus bei der Entwicklung lag auf einer guten User Experience. Wir haben daher eine Suchfunktion ergänzt, damit die Nutzer bei vielen Auswahlmöglichkeiten schneller zum Ziel finden.
Für Entwickler hat das Widget den Vorteil, dass man eigene Komponenten für die Suchleiste, die Liste aller Optionen und die Fußleiste vergeben kann. Das „react-select“ kommt bereits mit einem grundlegenden Stylesheet, so dass es direkt in ein vorhandenes Projekt eingebunden und sofort verwendet werden kann. Es lässt sich leicht konfigurieren und hat bis auf React keinerlei Abhängigkeiten.
Erweiterung des Widgets
In diesem Blogartikel stellen wir an einem Beispiel dar, wie die Grundfunktion des Widgets um einige nützliche Funktionen erweitert werden kann.
Eine oft gewünschte Funktion für ein Select-Widget ist das Erstellen von zusätzlichen Auswahlmöglichkeiten durch den Nutzer direkt im Widget.
Der „kleine“ Effekt hat große Auswirkungen auf die User Experience. So kann der Benutzer der Anwendung auf der selben Seite bleiben, ohne sich durch viele Untermenüs kämpfen zu müssen oder die Seite neu zu laden, um eine neue Option zu erstellen.
-
Zunächst wird das Select gerendert.
Um die Optionen nachher zu erweitern, werden diese im React State festgehalten.import React from 'react'; class SelectContainer extends React.Component { constructor(props) { this.state = { choices: [] } } render() { return ( <Select choices={this.state.choices} /> ) } }
-
Damit in den Erstellen-Dialog gewechselt werden kann, muss das Select um eine Fußzeile erweitert werden:
Dafür erstellen wir zuerst eine leere Fußzeile, in die wir dann die gewünschten Buttons und Styles einfügen. Die Fußleiste bekommt anschließend zusätzliche Parameter, um mit der Elternkomponente, in der das „react-select“ implementiert ist, zu kommunizieren. Mit einem Klick auf den Button schalten wir zwischen der Auswahlliste und einem Erstellen-Dialog hin und her.this.state = { choices: [], creating: false, } … <Select choices={this.state.choices} footerComponent={this.state.creating ? () => null : Footer } footerComponentProps={{ create: () => this.setState({creating: true}) }} /> const Footer = ({create}) => ( <button onClick={create}>Füge eine Hunderasse hinzu</button> );
-
Das Formular zum Erstellen einer Option arbeitet unabhängig vom „react-select“. Die Logik zur Implementierung kann entweder mithilfe einer bestehenden Bibliothek oder manuell implementiert werden.
Um das Beispiel kompakt zu halten, wird der Wert eines Input-Feldes innerhalb des React States festgehalten und mit einem Button abgesendet.import React, {useState} from 'react'; import ChoiceList from '../../../src/js/Component/ChoiceList'; … <Select … choiceListComponent={this.state.creating ? CreateDialog : ChoiceList} choiceListComponentProps={{ add: (value) => { // Logik, um den Wert der Bestehenden Liste hinzuzufügen } }} /> … const CreateDialog = ({add, toggleChoice}) => { const [value, setValue] = useState(''); return ( <> <input type="text" onChange={(e) => setValue(e.target.value)} /> <button onClick={() => { // Callback von der Elternkomponente add(value); }}> Erstellen </button> </> ) }
-
Die benutzerdefinierte Liste bekommt zusätzlich zu den eigenen definierten Methoden die von „react-select“ bereitgestellte Methode „toggleChoice“, welche zwei Parameter übergeben bekommt. Der erste Parameter, entspricht dem Wert, der im Widget ausgewählt wird. Mit dem zweiten Parameter wird gesteuert, ob sich die Liste nach erfolgter Auswahl schließen soll. Will man die erstellten Werte serverseitig validieren und anschließend persistieren, so kann man dementsprechend die Elternklasse „SelectContainer“ erweitern. Diese gibt dann bei der Erstellung des Wertes ein „Promise“ zurück, was entweder erfüllt ist oder bei Nichterfüllung zusätzliche Fehlermeldungen zurück gibt.
… const CreateDialog = ({add, toggleChoice}) => { const [value, setValue] = useState(''); return ( <> <input type="text" onChange={(e) => setValue(e.target.value)} /> <button onClick={() => { ... // Erstellten Wert als Vorauswahl setzen toggleChoice(value, true); }}> Erstellen </button> </> ) }
-
Das fertige Widget!
Das gesamte Beispiel lässt sich im „example“ Ordner der Bibliothek finden.
Happy hacking!