From 4d8febcc3f637b9aaa63abbddbcf8d3f72a64543 Mon Sep 17 00:00:00 2001 From: Gerd Date: Thu, 24 Sep 2026 19:14:16 +0200 Subject: [PATCH] fix(select): Anzeige bei asynchron nachgeladenen Optionen nachziehen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beim oninit war attrs.value teils keiner Option zuzuordnen, weil die Optionen (z.B. Kundenliste) asynchron geladen werden — das Feld blieb dauerhaft leer, da lastSyncedValue bereits gesetzt war und der Sync im view nicht mehr griff. syncPending markiert die offene Synchronisierung und wiederholt sie im view, bis eine passende Option existiert; Tippen verwirft das Flag, damit die Nutzereingabe nicht überschrieben wird. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe --- Client/Components/widgets/select.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Client/Components/widgets/select.ts b/Client/Components/widgets/select.ts index 247b6c5..ae064ea 100644 --- a/Client/Components/widgets/select.ts +++ b/Client/Components/widgets/select.ts @@ -52,6 +52,11 @@ export const Select: m.ClosureComponent = () => { // gesetzt; ändert sich der attrs.value von außen (z.B. Zurücksetzen // eines Filters im Eltern-View), wird der Text im view nachgezogen. let lastSyncedValue: any = undefined + // True, solange der attrs.value noch keinem label zugeordnet werden + // konnte — typischerweise weil die Optionen asynchron geladen werden + // und beim oninit noch leer waren. Der view wiederholt die Synchro- + // nisierung dann, bis eine passende Option existiert. + let syncPending: boolean = false // Zeigt die Optionliste ungefiltert an, unabhängig vom Suchtext. // Wird vom Öffnen-Button gesetzt (neben dem Clear-Button) und beim // Tippen, bei der Auswahl und mit Escape zurückgesetzt. @@ -77,6 +82,10 @@ export const Select: m.ClosureComponent = () => { const option = options.find((o: iSelectOption) => o.value === value) search = option ? option.label : "" lastSyncedValue = value + // Konnte der value keinem label zugeordnet werden, bleibt die + // Synchronisierung offen und wird im view wiederholt, sobald + // die Optionen (asynchron) nachgeladen wurden. + syncPending = !option } /** @@ -114,7 +123,7 @@ export const Select: m.ClosureComponent = () => { // Initialisieren und bei der Optionsauswahl gesetzt. Ändert der // Eltern-View den attrs.value (z.B. Zurücksetzen eines Filters), // wird der angezeigte Text hier auf das neue label synchronisiert. - if (vnode.attrs.value !== lastSyncedValue) { + if (vnode.attrs.value !== lastSyncedValue || syncPending) { syncSearchZumValue(vnode.attrs.value, vnode.attrs.options) } const isReadonly = vnode.attrs.readonly === true @@ -132,6 +141,9 @@ export const Select: m.ClosureComponent = () => { oninput: (e: Event) => { if (isReadonly) { return } search = (e.target as HTMLInputElement).value + // Der Nutzer tippt selbst — eine offene Synchronisierung + // (asynchron nachgeladene Optionen) nicht mehr nachziehen. + syncPending = false // Tippen sucht wieder im Suchtext-Basis. showAll = false isOpen = true