@samitouri / QOSami-HFS / commits / ba802951

admin/options: automatic scroll to show errors

Massimo Melina committed Sep 13, 2025 at 17:10 UTC ba802951b7c42f86f9c55670826b7f698cf7b8ff
1 file changed +11 -4
mui-grid-form/index.ts
+11 -4
@@ -71,6 +71,7 @@ export interface FormProps<Values> extends Partial<BoxProps> {
71 }
72 enum Phase { Idle, WaitValues, Validating }
73
74 +const ERROR_CLASS = 'field-container-with-error'
75 export function Form<Values extends Dict>({
76 fields,
77 values,
@@ -102,6 +103,7 @@ export function Form<Values extends Dict>({
103 const [phase, setPhase] = useState(Phase.Idle)
104 const submitAfterValidation = useRef(false)
105 const validateUpTo = useRef('')
106 + formRef ||= useRef()
107 useEffect(() => void phaseChange(), [phase]) //eslint-disable-line
108 const keyMet: Dict<number> = {}
109
@@ -135,12 +137,13 @@ export function Form<Values extends Dict>({
137 let errMsg = errors[k] || error || fieldExceptions[k]
138 if (errMsg === true)
139 errMsg = "Not valid"
140 + const anyError = Boolean(errMsg || error) || undefined
141 if (k) {
142 const originalValue = row.hasOwnProperty('value') ? row.value : getValueFor(k)
143 Object.assign(field, {
144 name: k,
145 value: toField(originalValue),
143 - error: Boolean(errMsg || error) || undefined,
146 + error: anyError,
147 setApi(api) { apis[k] = api },
148 onKeyDown(event: any) {
149 if (saveOnEnter && event.key === 'Enter')
@@ -175,7 +178,7 @@ export function Form<Values extends Dict>({
178 field.label = labelFromKey(k)
179 }
180 const n = (keyMet[k] = (keyMet[k] || 0) + 1)
178 - return h(Grid, { key: k ? k + n : idx, xs, sm, md, lg, xl, ...parentProps },
181 + return h(Grid, { key: k ? k + n : idx, xs, sm, md, lg, xl, className: anyError && ERROR_CLASS, ...parentProps },
182 before,
183 isValidElement(comp) ? comp : h(comp, field),
184 after
@@ -248,8 +251,12 @@ export function Form<Values extends Dict>({
251 onValidation?.(anyError && errs)
252 try {
253 if (!submitAfterValidation.current) return
251 - if (anyError)
252 - return await onError?.(MSG)
254 + if (anyError) {
255 + try { return await onError?.(MSG) }
256 + finally {
257 + setTimeout(() => formRef?.current?.querySelector('.' + ERROR_CLASS)?.scrollIntoView({ block: 'center' }), 1)
258 + }
259 + }
260 const cb = saveBtn && saveBtn.onClick
261 if (cb) // @ts-ignore
262 await cb()