From 48c1b69af9169835fc572fc88092462515ed6a3b Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Fri, 3 Jul 2026 13:30:34 +0900 Subject: [PATCH] fix: use form ID instead of object reference for event delegation Problem: After Blazor hydration, the form element is a new object instance. The event delegation code compared event.target (new form) with the stale form reference from before hydration, causing the comparison to fail and the submit event to be ignored. Solution: Compare form IDs instead of object references. - Old: if (event.target !== form) return; // object reference (stale after hydration) - New: if (event.target.id !== 'admin-login-form') return; // ID comparison (survives hydration) Also update all form references inside the handler to use event.target (currentForm) instead of the stale form variable to ensure we're working with the actual DOM element after hydration. Result: Login form submit event now fires correctly after Blazor hydration. Co-Authored-By: Claude Haiku 4.5 --- src/TaxBaik.Web/wwwroot/js/admin-session.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/TaxBaik.Web/wwwroot/js/admin-session.js b/src/TaxBaik.Web/wwwroot/js/admin-session.js index 8202056..cc25b94 100644 --- a/src/TaxBaik.Web/wwwroot/js/admin-session.js +++ b/src/TaxBaik.Web/wwwroot/js/admin-session.js @@ -291,16 +291,18 @@ window.taxbaikAdminSession = { window.taxbaikAdminSession.traceUiState('admin-login', 'bindLoginForm attached'); // 프리렌더 후 Blazor 하이드레이션이 이벤트 리스너를 제거할 수 있으므로, - // document 전체에서 submit 이벤트를 캡처하고, 우리의 form인지 확인 + // document 전체에서 submit 이벤트를 캡처하고, form ID로 우리의 form인지 확인 + // (객체 참조 비교는 Blazor 하이드레이션 후 stale이 될 수 있으므로 ID 비교 사용) document.addEventListener('submit', async function (event) { - if (event.target !== form) return; // 다른 form은 무시 + if (event.target.id !== 'admin-login-form') return; // 다른 form은 무시 event.preventDefault(); - const username = form.querySelector('input[placeholder="사용자명"]')?.value?.trim() || ''; - const password = form.querySelector('input[placeholder="비밀번호"]')?.value || ''; - const rememberMe = form.querySelector('input[type="checkbox"]')?.checked || false; - const existing = form.parentElement.querySelector('.login-error-message'); - const submitButton = form.querySelector('button[type="submit"]'); + const currentForm = event.target; // Blazor 하이드레이션 후 최신 form 참조 + const username = currentForm.querySelector('input[placeholder="사용자명"]')?.value?.trim() || ''; + const password = currentForm.querySelector('input[placeholder="비밀번호"]')?.value || ''; + const rememberMe = currentForm.querySelector('input[type="checkbox"]')?.checked || false; + const existing = currentForm.parentElement.querySelector('.login-error-message'); + const submitButton = currentForm.querySelector('button[type="submit"]'); if (existing) existing.remove(); if (submitButton) submitButton.disabled = true; @@ -365,7 +367,7 @@ window.taxbaikAdminSession = { const errorMessage = document.createElement('div'); errorMessage.className = 'mud-alert mud-alert-filled-error login-error-message mb-4'; errorMessage.textContent = '로그인 중 오류가 발생했습니다.'; - form.parentElement.insertBefore(errorMessage, form); + currentForm.parentElement.insertBefore(errorMessage, currentForm); } finally { if (submitButton) submitButton.disabled = false; }