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()