mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Form focus (#7008)
* Add 'focus' property for ApiFormProps * Attempt to focus on particular field * Improve setFocus hook - Set the focus at the appropriate time - Auto focus on first field if not specified * Add custom focus field * Update useEffect property list
This commit is contained in:
parent
40e867896b
commit
36c00803b0
@ -66,6 +66,7 @@ export interface ApiFormProps {
|
|||||||
pathParams?: PathParams;
|
pathParams?: PathParams;
|
||||||
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
method?: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
|
||||||
fields?: ApiFormFieldSet;
|
fields?: ApiFormFieldSet;
|
||||||
|
focus?: string;
|
||||||
initialData?: FieldValues;
|
initialData?: FieldValues;
|
||||||
submitText?: string;
|
submitText?: string;
|
||||||
submitColor?: string;
|
submitColor?: string;
|
||||||
@ -292,7 +293,48 @@ export function ApiForm({
|
|||||||
});
|
});
|
||||||
initialDataQuery.refetch();
|
initialDataQuery.refetch();
|
||||||
}
|
}
|
||||||
}, []);
|
}, [props.fetchInitialData]);
|
||||||
|
|
||||||
|
const isLoading = useMemo(
|
||||||
|
() =>
|
||||||
|
isFormLoading ||
|
||||||
|
initialDataQuery.isFetching ||
|
||||||
|
optionsLoading ||
|
||||||
|
isSubmitting ||
|
||||||
|
!props.fields,
|
||||||
|
[
|
||||||
|
isFormLoading,
|
||||||
|
initialDataQuery.isFetching,
|
||||||
|
isSubmitting,
|
||||||
|
props.fields,
|
||||||
|
optionsLoading
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
const [initialFocus, setInitialFocus] = useState<string>('');
|
||||||
|
|
||||||
|
// Update field focus when the form is loaded
|
||||||
|
useEffect(() => {
|
||||||
|
let focusField = props.focus ?? '';
|
||||||
|
|
||||||
|
if (!focusField) {
|
||||||
|
// If a focus field is not specified, then focus on the first available field
|
||||||
|
Object.entries(props.fields ?? {}).forEach(([fieldName, field]) => {
|
||||||
|
if (focusField || field.read_only || field.disabled || field.hidden) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
focusField = fieldName;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLoading || initialFocus == focusField) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.setFocus(focusField);
|
||||||
|
setInitialFocus(focusField);
|
||||||
|
}, [props.focus, props.fields, form.setFocus, isLoading, initialFocus]);
|
||||||
|
|
||||||
const submitForm: SubmitHandler<FieldValues> = async (data) => {
|
const submitForm: SubmitHandler<FieldValues> = async (data) => {
|
||||||
setNonFieldErrors([]);
|
setNonFieldErrors([]);
|
||||||
@ -392,22 +434,6 @@ export function ApiForm({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const isLoading = useMemo(
|
|
||||||
() =>
|
|
||||||
isFormLoading ||
|
|
||||||
initialDataQuery.isFetching ||
|
|
||||||
optionsLoading ||
|
|
||||||
isSubmitting ||
|
|
||||||
!props.fields,
|
|
||||||
[
|
|
||||||
isFormLoading,
|
|
||||||
initialDataQuery.isFetching,
|
|
||||||
isSubmitting,
|
|
||||||
props.fields,
|
|
||||||
optionsLoading
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onFormError = useCallback<SubmitErrorHandler<FieldValues>>(() => {
|
const onFormError = useCallback<SubmitErrorHandler<FieldValues>>(() => {
|
||||||
props.onFormError?.();
|
props.onFormError?.();
|
||||||
}, [props.onFormError]);
|
}, [props.onFormError]);
|
||||||
|
@ -188,7 +188,7 @@ export function ApiFormField({
|
|||||||
return (
|
return (
|
||||||
<TextInput
|
<TextInput
|
||||||
{...reducedDefinition}
|
{...reducedDefinition}
|
||||||
ref={ref}
|
ref={field.ref}
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
type={definition.field_type}
|
type={definition.field_type}
|
||||||
value={value || ''}
|
value={value || ''}
|
||||||
@ -226,7 +226,7 @@ export function ApiFormField({
|
|||||||
<NumberInput
|
<NumberInput
|
||||||
{...reducedDefinition}
|
{...reducedDefinition}
|
||||||
radius="sm"
|
radius="sm"
|
||||||
ref={ref}
|
ref={field.ref}
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
value={numericalValue}
|
value={numericalValue}
|
||||||
error={error?.message}
|
error={error?.message}
|
||||||
@ -256,7 +256,7 @@ export function ApiFormField({
|
|||||||
<FileInput
|
<FileInput
|
||||||
{...reducedDefinition}
|
{...reducedDefinition}
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
ref={ref}
|
ref={field.ref}
|
||||||
radius="sm"
|
radius="sm"
|
||||||
value={value}
|
value={value}
|
||||||
error={error?.message}
|
error={error?.message}
|
||||||
|
@ -52,6 +52,7 @@ export default function DateField({
|
|||||||
<DateInput
|
<DateInput
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
radius="sm"
|
radius="sm"
|
||||||
|
ref={field.ref}
|
||||||
type={undefined}
|
type={undefined}
|
||||||
error={error?.message}
|
error={error?.message}
|
||||||
value={dateValue}
|
value={dateValue}
|
||||||
|
@ -269,6 +269,7 @@ export function RelatedModelField({
|
|||||||
<Select
|
<Select
|
||||||
id={fieldId}
|
id={fieldId}
|
||||||
value={currentValue}
|
value={currentValue}
|
||||||
|
ref={field.ref}
|
||||||
options={data}
|
options={data}
|
||||||
filterOption={null}
|
filterOption={null}
|
||||||
onInputChange={(value: any) => {
|
onInputChange={(value: any) => {
|
||||||
|
@ -132,6 +132,7 @@ export default function ParametricPartTable({
|
|||||||
url: ApiEndpoints.part_parameter_list,
|
url: ApiEndpoints.part_parameter_list,
|
||||||
title: t`Add Part Parameter`,
|
title: t`Add Part Parameter`,
|
||||||
fields: partParameterFields,
|
fields: partParameterFields,
|
||||||
|
focus: 'data',
|
||||||
onFormSuccess: (parameter: any) => {
|
onFormSuccess: (parameter: any) => {
|
||||||
updateParameterRecord(selectedPart, parameter);
|
updateParameterRecord(selectedPart, parameter);
|
||||||
},
|
},
|
||||||
@ -146,6 +147,7 @@ export default function ParametricPartTable({
|
|||||||
title: t`Edit Part Parameter`,
|
title: t`Edit Part Parameter`,
|
||||||
pk: selectedParameter,
|
pk: selectedParameter,
|
||||||
fields: partParameterFields,
|
fields: partParameterFields,
|
||||||
|
focus: 'data',
|
||||||
onFormSuccess: (parameter: any) => {
|
onFormSuccess: (parameter: any) => {
|
||||||
updateParameterRecord(selectedPart, parameter);
|
updateParameterRecord(selectedPart, parameter);
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,9 @@ export function PartParameterTable({ partId }: { partId: any }) {
|
|||||||
|
|
||||||
const partParameterFields: ApiFormFieldSet = useMemo(() => {
|
const partParameterFields: ApiFormFieldSet = useMemo(() => {
|
||||||
return {
|
return {
|
||||||
part: {},
|
part: {
|
||||||
|
disabled: true
|
||||||
|
},
|
||||||
template: {},
|
template: {},
|
||||||
data: {}
|
data: {}
|
||||||
};
|
};
|
||||||
@ -105,6 +107,7 @@ export function PartParameterTable({ partId }: { partId: any }) {
|
|||||||
url: ApiEndpoints.part_parameter_list,
|
url: ApiEndpoints.part_parameter_list,
|
||||||
title: t`New Part Parameter`,
|
title: t`New Part Parameter`,
|
||||||
fields: partParameterFields,
|
fields: partParameterFields,
|
||||||
|
focus: 'template',
|
||||||
initialData: {
|
initialData: {
|
||||||
part: partId
|
part: partId
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user