simpler api for Form.save

Massimo Melina committed Mar 16, 2022 at 15:56 UTC 3547d3da893d46cf9854dcb64d479570ac5379ec
1 file changed +26 -21
admin/src/Form.ts
+26 -21
@@ -33,7 +33,7 @@ interface FormProps {
33 defaults?: (f:FieldDescriptor) => Dict | any
34 values: Dict
35 set: (v: any, fieldK: string) => void
36 - save?: Partial<Parameters<typeof Button>[0]>
36 + save: Partial<Parameters<typeof Button>[0]> | (()=>any)
37 stickyBar?: boolean
38 addToBar?: ReactNode[]
39 barSx?: Dict
@@ -43,28 +43,28 @@ interface FormProps {
43 export function Form({ fields, values, set, defaults, save, stickyBar, addToBar=[], barSx, formRef, onError, ...rest }: FormProps) {
44 const [loading, setLoading] = useStateMounted(false)
45 const [errors, setErrors] = useStateMounted<Dict>({})
46 - const onClick = save?.onClick
47 - if (onClick)
48 - save.onClick = async function (ev) {
49 - setLoading(true)
50 - try {
51 - for (const f of fields) {
52 - if (!f || isValidElement(f) || !f.k || !f.validate) continue
53 - const res = await f.validate(values?.[f.k], { values, fields })
54 - if (res !== true)
55 - return setErrors({ [f.k]: res || true })
56 - }
57 - setErrors({})
58 - return await onClick(ev)
46 + const saveBtn = typeof save === 'function' ? { onClick: save } : save
47 + const { onClick } = saveBtn
48 + saveBtn.onClick = onClick && async function (ev) {
49 + setLoading(true)
50 + try {
51 + for (const f of fields) {
52 + if (!f || isValidElement(f) || !f.k || !f.validate) continue
53 + const res = await f.validate(values?.[f.k], { values, fields })
54 + if (res !== true)
55 + return setErrors({ [f.k]: res || true })
56 }
60 - catch(e) { onError?.(e) }
61 - finally { setLoading(false) }
57 + setErrors({})
58 + return await onClick(ev)
59 }
60 + catch(e) { onError?.(e) }
61 + finally { setLoading(false) }
62 + }
63
64 const [pendingSubmit, setPendingSubmit] = useStateMounted(false)
65 useEffect(() => {
66 if (!pendingSubmit) return
67 - setTimeout(save?.onClick!)
67 + setTimeout(saveBtn.onClick!)
68 setPendingSubmit(false)
69 }, [pendingSubmit]) //eslint-disable-line
70
@@ -74,7 +74,7 @@ export function Form({ fields, values, set, defaults, save, stickyBar, addToBar=
74 ev.preventDefault()
75 },
76 onKeyDown(ev) {
77 - if (!save?.disabled && (ev.ctrlKey || ev.metaKey) && ev.key === 'Enter')
77 + if (!saveBtn.disabled && (ev.ctrlKey || ev.metaKey) && ev.key === 'Enter')
78 setPendingSubmit(true) // we need to let outer component perform its state changes
79 }
80 },
@@ -169,14 +169,19 @@ export function StringField({ value, onChange, fromField=_.identity, toField=_.i
169 InputLabelProps: state || props.placeholder ? { shrink: true } : undefined,
170 ...props,
171 value: state,
172 - onChange(event) {
173 - setState(event.target.value)
172 + onChange(ev) {
173 + props.onChange?.(ev)
174 + setState(ev.target.value)
175 },
176 onKeyDown(ev) {
177 + props.onKeyDown?.(ev)
178 if (ev.key === 'Enter')
179 go(ev)
180 },
179 - onBlur: go
181 + onBlur(ev) {
182 + props.onBlur?.(ev)
183 + go(ev)
184 + }
185 })
186
187 function go(event: any) {