From 74e82eb64386042b77f77b0d775191b2710ce05d Mon Sep 17 00:00:00 2001 From: Kevin Adametz Date: Wed, 8 Jul 2026 13:29:12 +0000 Subject: [PATCH] Form-Hooks: Fehl-Scroll aufs erste Feld bei Live-Validation behoben MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zwei Bugs im Scroll-zum-Fehler-Helper: '[wire\:submit]' matchte das
selbst, sodass jeder Klick in ein Feld den Scroll armierte (sichtbar beim USt-ID-Live-Check im Profil); und der leere, versteckte Flux-Error-Container unter jedem Feld galt wegen Whitespace als ':not(:empty)' — fokussiert wurde dadurch grundlos das erste Feld. Enter-Submit wird jetzt über das submit-Event erkannt, Fehlerfelder nur noch bei echtem Fehlertext. Co-Authored-By: Claude Fable 5 --- resources/js/portal-form-hooks.js | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/resources/js/portal-form-hooks.js b/resources/js/portal-form-hooks.js index 3e945f98..142d4e6a 100644 --- a/resources/js/portal-form-hooks.js +++ b/resources/js/portal-form-hooks.js @@ -25,11 +25,13 @@ let scrollPending = false; // Selektoren für Buttons, die wir als "Submit-Intent" interpretieren. + // Bewusst NICHT '[wire\\:submit]': das matcht das selbst, und da + // Klicks bubbeln, würde jeder Klick in irgendein Feld den Scroll armieren + // (Bug 08.07.: USt-ID-Live-Check sprang zum ersten Feld hoch). const SUBMIT_SELECTORS = [ '[wire\\:click*="save"]', '[wire\\:click*="submit"]', '[wire\\:click*="update"]', - '[wire\\:submit]', 'button[type="submit"]', ].join(','); @@ -40,6 +42,14 @@ } }, true); + // Enter-Submit in wire:submit-Forms kommt nicht als Button-Klick an — + // das submit-Event deckt ihn ab (Livewire preventet nur den Default). + document.addEventListener('submit', (event) => { + if (event.target.matches('[wire\\:submit]')) { + scrollPending = true; + } + }, true); + document.addEventListener('livewire:init', () => { if (!window.Livewire || typeof window.Livewire.hook !== 'function') { return; @@ -53,9 +63,13 @@ scrollPending = false; requestAnimationFrame(() => { + // Flux rendert unter JEDEM Feld einen (hidden) Error-Container + // mit Whitespace-Inhalt — ':not(:empty)' matcht den daher auch + // ohne Fehler. Nur Container mit echtem Text zählen. const invalid = document.querySelector('[data-flux-control][aria-invalid="true"]') || document.querySelector('[aria-invalid="true"]') - || document.querySelector('[data-flux-error]:not(:empty)'); + || Array.from(document.querySelectorAll('[data-flux-error]')) + .find((el) => el.textContent.trim() !== ''); if (!invalid) { return;