diff --git a/src/frontend/src/components/forms/ApiForm.tsx b/src/frontend/src/components/forms/ApiForm.tsx
index 742b1e94bd..bb8d203d9e 100644
--- a/src/frontend/src/components/forms/ApiForm.tsx
+++ b/src/frontend/src/components/forms/ApiForm.tsx
@@ -6,7 +6,7 @@ import {
Paper,
Text
} from '@mantine/core';
-import { Button, Group, Stack } from '@mantine/core';
+import { Button, Divider, Group, Stack } from '@mantine/core';
import { useId } from '@mantine/hooks';
import { notifications } from '@mantine/notifications';
import { useQuery } from '@tanstack/react-query';
@@ -104,7 +104,7 @@ export function OptionsApiForm({
[props.url, props.pk, props.pathParams]
);
- const { data } = useQuery({
+ const optionsQuery = useQuery({
enabled: true,
queryKey: [
'form-options-data',
@@ -139,18 +139,12 @@ export function OptionsApiForm({
const formProps: ApiFormProps = useMemo(() => {
const _props = { ...props };
- // This forcefully overrides initial data
- // Currently, most modals do not get pre-loaded correctly
- if (!data) {
- _props.fields = undefined;
- }
-
if (!_props.fields) return _props;
for (const [k, v] of Object.entries(_props.fields)) {
_props.fields[k] = constructField({
field: v,
- definition: data?.[k]
+ definition: optionsQuery?.data?.[k]
});
// If the user has specified initial data, use that value here
@@ -162,16 +156,30 @@ export function OptionsApiForm({
}
return _props;
- }, [data, props]);
+ }, [optionsQuery.data, props]);
- return ;
+ return (
+
+ );
}
/**
* An ApiForm component is a modal form which is rendered dynamically,
* based on an API endpoint.
*/
-export function ApiForm({ id, props }: { id: string; props: ApiFormProps }) {
+export function ApiForm({
+ id,
+ props,
+ optionsLoading
+}: {
+ id: string;
+ props: ApiFormProps;
+ optionsLoading: boolean;
+}) {
const defaultValues: FieldValues = useMemo(() => {
let defaultValuesMap = mapFields(props.fields ?? {}, (_path, field) => {
return field.value ?? field.default ?? undefined;
@@ -227,6 +235,7 @@ export function ApiForm({ id, props }: { id: string; props: ApiFormProps }) {
try {
// Await API call
let response = await api.get(url);
+
// Define function to process API response
const processFields = (fields: ApiFormFieldSet, data: NestedDict) => {
const res: NestedDict = {};
@@ -387,9 +396,16 @@ export function ApiForm({ id, props }: { id: string; props: ApiFormProps }) {
() =>
isFormLoading ||
initialDataQuery.isFetching ||
+ optionsLoading ||
isSubmitting ||
!props.fields,
- [isFormLoading, initialDataQuery.isFetching, isSubmitting, props.fields]
+ [
+ isFormLoading,
+ initialDataQuery.isFetching,
+ isSubmitting,
+ props.fields,
+ optionsLoading
+ ]
);
const onFormError = useCallback>(() => {
@@ -431,16 +447,17 @@ export function ApiForm({ id, props }: { id: string; props: ApiFormProps }) {
)}
- {Object.entries(props.fields ?? {}).map(
- ([fieldName, field]) => (
-
- )
- )}
+ {!optionsLoading &&
+ Object.entries(props.fields ?? {}).map(
+ ([fieldName, field]) => (
+
+ )
+ )}
{props.postFormContent}
@@ -449,6 +466,7 @@ export function ApiForm({ id, props }: { id: string; props: ApiFormProps }) {
{/* Footer with Action Buttons */}
+
{props.actions?.map((action, i) => (
diff --git a/src/frontend/src/functions/forms.tsx b/src/frontend/src/functions/forms.tsx
index 2bd7cc994d..2fc5a46e9f 100644
--- a/src/frontend/src/functions/forms.tsx
+++ b/src/frontend/src/functions/forms.tsx
@@ -246,7 +246,7 @@ export function openModalApiForm(props: OpenApiFormProps) {
children: (
-
+
)
});