Wir müssen untersuchen, wie wir uns die API für die Auswahl-/Kombinationsbox in einer Webkomponentenwelt vorstellen.
Eine Auswahl- oder Kombinationsbox kann möglicherweise dieselbe Komponente sein, aber vielleicht möchten wir sie aufteilen. Das ist noch sehr unentschieden.
Vergleichen Sie verschiedene Komponentenbibliotheken / Designsystemansätze für eine Combobox / eine ausgewählte Komponente und erstellen Sie einen API-Vorschlag, der funktionieren würde.
Einige potenzielle Ressourcen:
Denken Sie daran, dass die Virtualisierung von Optionen ein Muss sein wird. Ist dies etwas, das wir auf der Webkomponentenschicht handhaben sollten oder ist dies etwas, das unsere Verbraucher auf einer potenziellen Framework-Schicht handhaben.
Testen und recherchieren Sie mit einer der oben genannten Webkomponenten in einem Angular-Setup mit virtuellem Scrollen für Optionen.
Versuchen Sie es auch mit der Webkomponente mit Reaction und Virtualisierung.
Wenn wir uns entscheiden, dies selbst zu handhaben, müssen wir einen Vorlagenmechanismus erstellen, der den Kontext für eine einmal erstellte Option festlegt.
Einige Ressourcen, um so etwas zu erreichen, könnten Microsoft-Graph-Toolkit sein
Das Ergebnis dieser Ausgabe sollte ein Überblick über unsere Optionen und Vor- und Nachteile sein, damit wir eine fundierte Entscheidung über das weitere Vorgehen treffen können.
Synchronisiere mit @heartdisease über API-Ideen für die Combobox. Er verbessert unsere aktuelle experimentelle Version für Angular
Ich habe das Microsoft-Graph-Toolkit TemplateHelper getestet, um die Combobox-Elemente mit einem bestimmten Kontext und einer in einem Slot bereitgestellten
Ich habe den Test in dieses Repo hochgeladen
Wir sollten also gut sein, die Liste der Elemente und (optional) eine Vorlage an die Combobox zu übergeben und die Virtualisierung "nur" hinzuzufügen, bevor die Elemente tatsächlich rendern, um nur x Elemente zu rendern, abhängig von der Scroll-Position und der Höhe des Overlay-Container.
Derzeit akzeptiert die Methode TemplateHelper.renderTemplate()
ein HTMLElement als Root-Knoten, eine Vorlage und einen Kontext (und optional einen zusätzlichen Kontext). Es erstellt alle Knoten gemäß der angegebenen Vorlage und hängt sie an den Wurzelknoten an.
Es ist möglicherweise besser, dieses Verhalten zu ändern und die Methode nur ein Template und einen Kontext akzeptieren zu lassen und das kompilierte Template zurückzugeben, um dann den zurückgegebenen HTML-Code direkt im lit-template in der Komponente ausgeben zu können.
Was denkst du?
ToDo
Wo soll der Ladespinner angezeigt werden?Wenn sie fokussiert ist, sollte sich die Combobox öffnen, wenn Sie die Taste Enter
, ArrowUp
oder ArrowDown
drücken oder wenn der Benutzer beginnt, einen Filter in das Eingabefeld einzugeben.
Im geöffneten Zustand sollte der Benutzer die Taste ArrowUp
/ ArrowDown
, um aus vorhandenen Optionen auszuwählen. Der Fokus für die Eingabe eines Filters sollte im Eingabefeld bleiben, Optionen sollten nicht tabellarisch sein. Der Auswahlstatus der Optionen sollte mit dem Attribut aria-selected
werden.
Eine Auswahl sollte mit der Taste Enter
übermittelt werden.
Durch Drücken der Taste Tab
oder Escape
sollte das Overlay geschlossen und das ausgewählte Element nicht geändert werden.
Beim Eintippen eines Filters und anschließendem Tabulator aus dem Eingabefeld sollte der Filter zurückgesetzt und das zuvor ausgewählte Element angezeigt werden.
Der Benutzer muss die öffnende und schließende Zeichenfolge der Vorlagenteile bereitstellen. Dies sollte entweder auf globaler oder komponentenbezogener Ebene möglich sein (muss noch entschieden werden).
Standardmäßig sind {{
und }}
.
_WIP_
Die ComboBox sollte in die Hauptkomponente FluidComboBox
, eine FluidComboBoxOptionsList
Komponente und eine FluidComboBoxOption
Komponente aufgeteilt werden.
Enthält ein FluidComboBoxOptionsList
, das wiederum FluidComboBoxOption
s enthält.
Behandelt das Öffnen und Schließen des Overlays und die Positionierung des Overlays.
Akzeptiert eine Vorlage als untergeordnetes Element, das die Basis HTMLElement
s akzeptiert.
Beim Bereitstellen einer Vorlage muss die öffnende und schließende Zeichenfolge, die für Vorlagenbindungen verwendet wird, festgelegt werden.
| Name | Geplant für | Typ | Standard | Beschreibung |
| -------------- | ------------ | -------- | -------- | -------------------------------------------------- ------------------------------------------ |
| Optionen | MVP | Array | [] | Array von Optionen zur Anzeige in FluidComboBoxOptionsList
|
| filterFn | MVP | (option: T) => boolean
| null
| Funktion zum Filtern von Optionen |
| renderOptionFn | MVP | (option: T) => string
| null
| Funktion zum Rendern von Optionen im Autovervollständigungsfenster |
| Platzhalter | MVP | Zeichenfolge | '' | Platzhalter, der im Eingabefeld angezeigt wird, wenn keine Option ausgewählt ist |
| deaktiviert | MVP | boolesch | falsch | Boolean, um zu bestimmen, ob die Combobox deaktiviert ist |
| Laden | MVP | boolesch | falsch | Boolescher Wert, um zu bestimmen, ob der Ladeindikator angezeigt wird |
| ausgewählt | MVP | beliebig | null | Element zur Vorauswahl |
| Mehrfachauswahl | v2 | boolesch | falsch | Boolean, um zu bestimmen, ob mehr als eine Option gleichzeitig ausgewählt werden kann |
| Name | Geplant für | Typ | Beschreibung |
| ---------------- | ------------ | --------------------------------- | -------------------------------------------------- ---- |
| ändern | MVP | FluidComboBoxChangeEvent | Ereignis wird ausgelöst, wenn sich der Wert ändert |
| Filterwechsel | MVP | FluidComboBoxFilterChangeEvent | Ereignis wird ausgelöst, wenn der Benutzer einen Wert zum Filtern eingibt |
| Auswahl-Änderung | MVP | FluidComboBoxSelectionChangeEvent | Ereignis wird ausgelöst, wenn sich die ausgewählte Option ändert |
Als Voraussetzung für die FluidComboBox müssen wir zunächst eine wiederverwendbare Ladespinner-Komponente implementieren.
ToDo
Fragen Sie UX nach L&F des neuen Ladespinners (oder ob das alte Design wiederverwendet werden kann).
Als Voraussetzung für die FluidComboBox müssen wir eine wiederverwendbare Komponente implementieren, die virtuelles Scrollen implementiert
um die Combobox mit einer großen Anzahl von Artikeln nutzen zu können.
Siehe auch:
https://github.com/WICG/virtual-scroller/blob/master/README.md
https://www.sitepen.com/blog/next-generation-virtual-scrolling/
https://dev.to/adamklein/build-your-own-virtual-scroll-part-i-11ib
https://blog.logrocket.com/virtual-scrolling-core-principles-and-basic-implementation-in-react/
Als Voraussetzung für die FluidComboBox müssen wir eine wiederverwendbare Popover-Komponente implementieren, die platziert werden kann
perfekt unter dem Eingabeelement der Combobox.
Diese Bibliothek sollte zum Implementieren dieser Komponente verwendet werden:
https://popper.js.org/docs/v2/
Bezüglich der Vorlagen habe ich einige Bedenken, da es für den Entwickler nicht sehr flexibel und umfangreich ist, nur Textersetzungen zu haben. Denken Sie an Texttransformationen über Funktionen oder einfache Bedingungen wie eine, wenn dies nicht möglich wäre, aber meiner Meinung nach erforderlich wäre.
Mein Ansatz wäre, Funktionen zu schreiben, die einen HTML-String zurückgeben, der in ein DocumentFragment eingefügt werden kann, das dann angehängt werden kann.
Mit Schreibfunktionen würden Sie die volle Flexibilität beim Transformieren von Bedingungen gewinnen.
Um eine einfache Möglichkeit dafür bereitzustellen, könnten wir etwas Ähnliches wie JSX htm nutzen , das in einen String gerendert werden kann, sodass kein Kompilieren erforderlich ist. Es hat auch einen sehr geringen Platzbedarf, von dem wir sprechen ~ 700 Bytes.
es könnte dann irgendwie verwendet werden wie:
<script type="text/template">
html`
<span>${text}</span>
{count > 0
<span>occurrences ${count}</span>
}
</div>
`;
</script>
import { render } from "preact-render-to-string";
const template = document.createElement('template');
template.innerHTML = render(option); // option is the script that can be passed via slot or input
const fragment = temp.content;
alternativ könnten wir getaggte Vorlagen verwenden https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates.
Dies wäre vielleicht die minimale Lösung.
Ich habe einige Tests durchgeführt und Angular entfernt leider alle Skript-Tags aus der Vorlage. Nur meine 2 Cent für das Deklarieren des Skripts in der Vorlage.
Vielleicht gehen wir mit einem funktionsorientierten Ansatz vor, damit die Combobox eine Eingabe hat, in der Sie eine Funktion zum Rendern der Vorlage bereitstellen können.
Ist es möglich, eine Funktion auf LitElements als Eigenschaft bereitzustellen? Denn dann würde ich das Rendering an den Consumer weitergeben wo er alle Flexibilitäten von Javascript in dieser Funktion hat. Die Funktion hat deklarierte Parameter (die Eingabe für das Template) und muss einen String zurückgeben.
Eine Standardimplementierung könnte wie folgt erfolgen:
_defaultTemplate<T>(display: string, value: T): string {
return `<option>${display}</option>`
}
Wie in #1513 besprochen, müssen wir das Popover richtig handhaben.
Ich bin mir nicht sicher, ob dies der richtige Ort ist, um die Eingabe zu diskutieren, die Teil der Combobox-Komponente ist - Aber da die Eingabe mit dem Fokus wächst, denke ich, dass es sinnvoll ist, die Box der Eingabekomponente zu erweitern, um den Raum einzunehmen, den der größte Zustand einnimmt hat.
Derzeit wächst die Eingabe um 16px in der Breite, sobald sie fokussiert ist. Daher würde ich vorschlagen, die Beschriftung + die Eingabe um eine Auffüllung von 8 zu verschieben. Dies würde bedeuten, dass, wenn sich mehrere Steuerelemente (Eingabe, Auswahl, ...) in einem vertikalen Formularlayout befinden, alle Beschriftungen aller Steuerelemente sein müssen ausgerichtet. Vielleicht ist ein Formularsteuerelement sinnvoll, das dafür sorgt, dass die Abstände für Beschriftungen + Eingaben vereinheitlicht werden.
Ich möchte den Vorschlag ändern, indem ich eine neue Eingabe zum Rendern der Anzeigezeichenfolge für die aktuelle Auswahloption hinzufüge:
| Name | Geplant für | Typ | Standard | Beschreibung |
| -------------- | ------------ | -------- | -------- | -------------------------------------------------- ------------------------------------------ |
| displayNameFn | MVP | (option: T) => string
| (Option) => `${Option}` | Funktion, die einen Anzeigestring (kein HTML erlaubt) für eine gegebene Option zurückgibt. |
Dies wäre auch eine einfache Lösung für dieses Problem: #1527
Etwas Kleines, das ich für wichtig halte: Die aktuelle DtCombobox verwendet value
einer Option als standardmäßigen Anzeigetext für die "ausgewählte Option". Ich denke, es ist viel sinnvoller, die Option textContent
.
1) textContent
ist immer ein UI-freundlicher Wert ( value
ist nur manchmal ein UI-freundlicher Wert)
2) Die Verwendung von textContent
ist das, was die Standard- select
tun
Wir werden dieses Thema schließen, da Webkomponenten nicht die Art sind, wie wir Komponenten in Zukunft erstellen möchten. Dies hängt mit einer Verschiebung der Prioritäten im Team zusammen.
Hilfreichster Kommentar
Anforderungen
Anforderungen für die nächsten Schritte
ToDo
Wo soll der Ladespinner angezeigt werden?Barrierefreiheit
Wenn sie fokussiert ist, sollte sich die Combobox öffnen, wenn Sie die Taste
Enter
,ArrowUp
oderArrowDown
drücken oder wenn der Benutzer beginnt, einen Filter in das Eingabefeld einzugeben.Im geöffneten Zustand sollte der Benutzer die Taste
ArrowUp
/ArrowDown
, um aus vorhandenen Optionen auszuwählen. Der Fokus für die Eingabe eines Filters sollte im Eingabefeld bleiben, Optionen sollten nicht tabellarisch sein. Der Auswahlstatus der Optionen sollte mit dem Attributaria-selected
werden.Eine Auswahl sollte mit der Taste
Enter
übermittelt werden.Durch Drücken der Taste
Tab
oderEscape
sollte das Overlay geschlossen und das ausgewählte Element nicht geändert werden.Beim Eintippen eines Filters und anschließendem Tabulator aus dem Eingabefeld sollte der Filter zurückgesetzt und das zuvor ausgewählte Element angezeigt werden.
Benutzerdefinierte Vorlagensyntax
Der Benutzer muss die öffnende und schließende Zeichenfolge der Vorlagenteile bereitstellen. Dies sollte entweder auf globaler oder komponentenbezogener Ebene möglich sein (muss noch entschieden werden).
Standardmäßig sind
{{
und}}
.API-Vorschlag
_WIP_
Die ComboBox sollte in die Hauptkomponente
FluidComboBox
, eineFluidComboBoxOptionsList
Komponente und eineFluidComboBoxOption
Komponente aufgeteilt werden.FluidComboBox
Enthält ein
FluidComboBoxOptionsList
, das wiederumFluidComboBoxOption
s enthält.Behandelt das Öffnen und Schließen des Overlays und die Positionierung des Overlays.
Akzeptiert eine Vorlage als untergeordnetes Element, das die Basis
HTMLElement
s akzeptiert.Beim Bereitstellen einer Vorlage muss die öffnende und schließende Zeichenfolge, die für Vorlagenbindungen verwendet wird, festgelegt werden.
Eingänge
| Name | Geplant für | Typ | Standard | Beschreibung |
| -------------- | ------------ | -------- | -------- | -------------------------------------------------- ------------------------------------------ |
| Optionen | MVP | Array | [] | Array von Optionen zur Anzeige in
FluidComboBoxOptionsList
|| filterFn | MVP |
(option: T) => boolean
|null
| Funktion zum Filtern von Optionen || renderOptionFn | MVP |
(option: T) => string
|null
| Funktion zum Rendern von Optionen im Autovervollständigungsfenster || Platzhalter | MVP | Zeichenfolge | '' | Platzhalter, der im Eingabefeld angezeigt wird, wenn keine Option ausgewählt ist |
| deaktiviert | MVP | boolesch | falsch | Boolean, um zu bestimmen, ob die Combobox deaktiviert ist |
| Laden | MVP | boolesch | falsch | Boolescher Wert, um zu bestimmen, ob der Ladeindikator angezeigt wird |
| ausgewählt | MVP | beliebig | null | Element zur Vorauswahl |
| Mehrfachauswahl | v2 | boolesch | falsch | Boolean, um zu bestimmen, ob mehr als eine Option gleichzeitig ausgewählt werden kann |
Ausgänge
| Name | Geplant für | Typ | Beschreibung |
| ---------------- | ------------ | --------------------------------- | -------------------------------------------------- ---- |
| ändern | MVP | FluidComboBoxChangeEvent | Ereignis wird ausgelöst, wenn sich der Wert ändert |
| Filterwechsel | MVP | FluidComboBoxFilterChangeEvent | Ereignis wird ausgelöst, wenn der Benutzer einen Wert zum Filtern eingibt |
| Auswahl-Änderung | MVP | FluidComboBoxSelectionChangeEvent | Ereignis wird ausgelöst, wenn sich die ausgewählte Option ändert |
FluidLoadingSpinner
Als Voraussetzung für die FluidComboBox müssen wir zunächst eine wiederverwendbare Ladespinner-Komponente implementieren.
ToDo
Fragen Sie UX nach L&F des neuen Ladespinners (oder ob das alte Design wiederverwendet werden kann).FluidVirtualScroller
Als Voraussetzung für die FluidComboBox müssen wir eine wiederverwendbare Komponente implementieren, die virtuelles Scrollen implementiert
um die Combobox mit einer großen Anzahl von Artikeln nutzen zu können.
Siehe auch:
https://github.com/WICG/virtual-scroller/blob/master/README.md
https://www.sitepen.com/blog/next-generation-virtual-scrolling/
https://dev.to/adamklein/build-your-own-virtual-scroll-part-i-11ib
https://blog.logrocket.com/virtual-scrolling-core-principles-and-basic-implementation-in-react/
FluidPopover
Als Voraussetzung für die FluidComboBox müssen wir eine wiederverwendbare Popover-Komponente implementieren, die platziert werden kann
perfekt unter dem Eingabeelement der Combobox.
Diese Bibliothek sollte zum Implementieren dieser Komponente verwendet werden:
https://popper.js.org/docs/v2/