diff --git a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
index 9ef95c60b..850c745b3 100644
--- a/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
+++ b/packages/codegen-ui-react/lib/__tests__/__snapshots__/studio-ui-codegen-react-forms.test.ts.snap
@@ -1,5 +1,565 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`amplify form renderer tests datastore form tests custom form tests should render a create form for child of 1:m relationship 1`] = `
+"/* eslint-disable */
+import * as React from \\"react\\";
+import {
+ Autocomplete,
+ Badge,
+ Button,
+ Divider,
+ Flex,
+ Grid,
+ Icon,
+ ScrollView,
+ Text,
+ TextField,
+} from \\"@aws-amplify/ui-react\\";
+import {
+ getOverrideProps,
+ useDataStoreBinding,
+} from \\"@aws-amplify/ui-react/internal\\";
+import { CompositeToy, CompositeDog } from \\"../models\\";
+import { fetchByPath, validateField } from \\"./utils\\";
+import { DataStore } from \\"aws-amplify\\";
+function ArrayField({
+ items = [],
+ onChange,
+ label,
+ inputFieldRef,
+ children,
+ hasError,
+ setFieldValue,
+ currentFieldValue,
+ defaultFieldValue,
+ lengthLimit,
+ getBadgeText,
+}) {
+ const labelElement = {label};
+ const [selectedBadgeIndex, setSelectedBadgeIndex] = React.useState();
+ const [isEditing, setIsEditing] = React.useState();
+ React.useEffect(() => {
+ if (isEditing) {
+ inputFieldRef?.current?.focus();
+ }
+ }, [isEditing]);
+ const removeItem = async (removeIndex) => {
+ const newItems = items.filter((value, index) => index !== removeIndex);
+ await onChange(newItems);
+ setSelectedBadgeIndex(undefined);
+ };
+ const addItem = async () => {
+ if (
+ currentFieldValue !== undefined &&
+ currentFieldValue !== null &&
+ currentFieldValue !== \\"\\" &&
+ !hasError
+ ) {
+ const newItems = [...items];
+ if (selectedBadgeIndex !== undefined) {
+ newItems[selectedBadgeIndex] = currentFieldValue;
+ setSelectedBadgeIndex(undefined);
+ } else {
+ newItems.push(currentFieldValue);
+ }
+ await onChange(newItems);
+ setIsEditing(false);
+ }
+ };
+ const arraySection = (
+
+ {!!items?.length && (
+
+ {items.map((value, index) => {
+ return (
+ {
+ setSelectedBadgeIndex(index);
+ setFieldValue(items[index]);
+ setIsEditing(true);
+ }}
+ >
+ {getBadgeText ? getBadgeText(value) : value.toString()}
+ {
+ event.stopPropagation();
+ removeItem(index);
+ }}
+ />
+
+ );
+ })}
+
+ )}
+
+
+ );
+ if (lengthLimit !== undefined && items.length >= lengthLimit && !isEditing) {
+ return (
+
+ {labelElement}
+ {arraySection}
+
+ );
+ }
+ return (
+
+ {labelElement}
+ {isEditing && children}
+ {!isEditing ? (
+ <>
+
+ >
+ ) : (
+
+ {(currentFieldValue || isEditing) && (
+
+ )}
+
+
+ )}
+ {arraySection}
+
+ );
+}
+export default function CreateCompositeToyForm(props) {
+ const {
+ clearOnSuccess = true,
+ onSuccess,
+ onError,
+ onSubmit,
+ onValidate,
+ onChange,
+ overrides,
+ ...rest
+ } = props;
+ const initialValues = {
+ kind: \\"\\",
+ color: \\"\\",
+ compositeDogCompositeToysName: undefined,
+ compositeDogCompositeToysDescription: undefined,
+ };
+ const [kind, setKind] = React.useState(initialValues.kind);
+ const [color, setColor] = React.useState(initialValues.color);
+ const [compositeDogCompositeToysName, setCompositeDogCompositeToysName] =
+ React.useState(initialValues.compositeDogCompositeToysName);
+ const [
+ compositeDogCompositeToysDescription,
+ setCompositeDogCompositeToysDescription,
+ ] = React.useState(initialValues.compositeDogCompositeToysDescription);
+ const [errors, setErrors] = React.useState({});
+ const resetStateValues = () => {
+ setKind(initialValues.kind);
+ setColor(initialValues.color);
+ setCompositeDogCompositeToysName(
+ initialValues.compositeDogCompositeToysName
+ );
+ setCurrentCompositeDogCompositeToysNameValue(undefined);
+ setCompositeDogCompositeToysDescription(
+ initialValues.compositeDogCompositeToysDescription
+ );
+ setCurrentCompositeDogCompositeToysDescriptionValue(undefined);
+ setErrors({});
+ };
+ const [
+ currentCompositeDogCompositeToysNameValue,
+ setCurrentCompositeDogCompositeToysNameValue,
+ ] = React.useState(undefined);
+ const compositeDogCompositeToysNameRef = React.createRef();
+ const [
+ currentCompositeDogCompositeToysDescriptionValue,
+ setCurrentCompositeDogCompositeToysDescriptionValue,
+ ] = React.useState(undefined);
+ const compositeDogCompositeToysDescriptionRef = React.createRef();
+ const compositeDogRecords = useDataStoreBinding({
+ type: \\"collection\\",
+ model: CompositeDog,
+ }).items;
+ const validations = {
+ kind: [{ type: \\"Required\\" }],
+ color: [{ type: \\"Required\\" }],
+ compositeDogCompositeToysName: [],
+ compositeDogCompositeToysDescription: [],
+ };
+ const runValidationTasks = async (
+ fieldName,
+ currentValue,
+ getDisplayValue
+ ) => {
+ const value = getDisplayValue
+ ? getDisplayValue(currentValue)
+ : currentValue;
+ let validationResponse = validateField(value, validations[fieldName]);
+ const customValidator = fetchByPath(onValidate, fieldName);
+ if (customValidator) {
+ validationResponse = await customValidator(value, validationResponse);
+ }
+ setErrors((errors) => ({ ...errors, [fieldName]: validationResponse }));
+ return validationResponse;
+ };
+ return (
+ {
+ event.preventDefault();
+ let modelFields = {
+ kind,
+ color,
+ compositeDogCompositeToysName,
+ compositeDogCompositeToysDescription,
+ };
+ const validationResponses = await Promise.all(
+ Object.keys(validations).reduce((promises, fieldName) => {
+ if (Array.isArray(modelFields[fieldName])) {
+ promises.push(
+ ...modelFields[fieldName].map((item) =>
+ runValidationTasks(fieldName, item)
+ )
+ );
+ return promises;
+ }
+ promises.push(
+ runValidationTasks(fieldName, modelFields[fieldName])
+ );
+ return promises;
+ }, [])
+ );
+ if (validationResponses.some((r) => r.hasError)) {
+ return;
+ }
+ if (onSubmit) {
+ modelFields = onSubmit(modelFields);
+ }
+ try {
+ Object.entries(modelFields).forEach(([key, value]) => {
+ if (typeof value === \\"string\\" && value.trim() === \\"\\") {
+ modelFields[key] = undefined;
+ }
+ });
+ await DataStore.save(new CompositeToy(modelFields));
+ if (onSuccess) {
+ onSuccess(modelFields);
+ }
+ if (clearOnSuccess) {
+ resetStateValues();
+ }
+ } catch (err) {
+ if (onError) {
+ onError(modelFields, err.message);
+ }
+ }
+ }}
+ {...getOverrideProps(overrides, \\"CreateCompositeToyForm\\")}
+ {...rest}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ kind: value,
+ color,
+ compositeDogCompositeToysName,
+ compositeDogCompositeToysDescription,
+ };
+ const result = onChange(modelFields);
+ value = result?.kind ?? value;
+ }
+ if (errors.kind?.hasError) {
+ runValidationTasks(\\"kind\\", value);
+ }
+ setKind(value);
+ }}
+ onBlur={() => runValidationTasks(\\"kind\\", kind)}
+ errorMessage={errors.kind?.errorMessage}
+ hasError={errors.kind?.hasError}
+ {...getOverrideProps(overrides, \\"kind\\")}
+ >
+ {
+ let { value } = e.target;
+ if (onChange) {
+ const modelFields = {
+ kind,
+ color: value,
+ compositeDogCompositeToysName,
+ compositeDogCompositeToysDescription,
+ };
+ const result = onChange(modelFields);
+ value = result?.color ?? value;
+ }
+ if (errors.color?.hasError) {
+ runValidationTasks(\\"color\\", value);
+ }
+ setColor(value);
+ }}
+ onBlur={() => runValidationTasks(\\"color\\", color)}
+ errorMessage={errors.color?.errorMessage}
+ hasError={errors.color?.hasError}
+ {...getOverrideProps(overrides, \\"color\\")}
+ >
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ kind,
+ color,
+ compositeDogCompositeToysName: value,
+ compositeDogCompositeToysDescription,
+ };
+ const result = onChange(modelFields);
+ value = result?.compositeDogCompositeToysName ?? value;
+ }
+ setCompositeDogCompositeToysName(value);
+ setCurrentCompositeDogCompositeToysNameValue(undefined);
+ }}
+ currentFieldValue={currentCompositeDogCompositeToysNameValue}
+ label={\\"Composite dog composite toys name\\"}
+ items={
+ compositeDogCompositeToysName ? [compositeDogCompositeToysName] : []
+ }
+ hasError={errors.compositeDogCompositeToysName?.hasError}
+ setFieldValue={setCurrentCompositeDogCompositeToysNameValue}
+ inputFieldRef={compositeDogCompositeToysNameRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: r?.name,
+ label: r?.name,
+ }))}
+ onSelect={({ id }) => {
+ setCurrentCompositeDogCompositeToysNameValue(id);
+ }}
+ onClear={() => {
+ setCurrentCompositeDogCompositeToysNameDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ if (errors.compositeDogCompositeToysName?.hasError) {
+ runValidationTasks(\\"compositeDogCompositeToysName\\", value);
+ }
+ setCurrentCompositeDogCompositeToysNameValue(value);
+ }}
+ onBlur={() =>
+ runValidationTasks(
+ \\"compositeDogCompositeToysName\\",
+ currentCompositeDogCompositeToysNameValue
+ )
+ }
+ errorMessage={errors.compositeDogCompositeToysName?.errorMessage}
+ hasError={errors.compositeDogCompositeToysName?.hasError}
+ ref={compositeDogCompositeToysNameRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"compositeDogCompositeToysName\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ kind,
+ color,
+ compositeDogCompositeToysName,
+ compositeDogCompositeToysDescription: value,
+ };
+ const result = onChange(modelFields);
+ value = result?.compositeDogCompositeToysDescription ?? value;
+ }
+ setCompositeDogCompositeToysDescription(value);
+ setCurrentCompositeDogCompositeToysDescriptionValue(undefined);
+ }}
+ currentFieldValue={currentCompositeDogCompositeToysDescriptionValue}
+ label={\\"Composite dog composite toys description\\"}
+ items={
+ compositeDogCompositeToysDescription
+ ? [compositeDogCompositeToysDescription]
+ : []
+ }
+ hasError={errors.compositeDogCompositeToysDescription?.hasError}
+ setFieldValue={setCurrentCompositeDogCompositeToysDescriptionValue}
+ inputFieldRef={compositeDogCompositeToysDescriptionRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: r?.description,
+ label: r?.description,
+ }))}
+ onSelect={({ id }) => {
+ setCurrentCompositeDogCompositeToysDescriptionValue(id);
+ }}
+ onClear={() => {
+ setCurrentCompositeDogCompositeToysDescriptionDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ if (errors.compositeDogCompositeToysDescription?.hasError) {
+ runValidationTasks(\\"compositeDogCompositeToysDescription\\", value);
+ }
+ setCurrentCompositeDogCompositeToysDescriptionValue(value);
+ }}
+ onBlur={() =>
+ runValidationTasks(
+ \\"compositeDogCompositeToysDescription\\",
+ currentCompositeDogCompositeToysDescriptionValue
+ )
+ }
+ errorMessage={
+ errors.compositeDogCompositeToysDescription?.errorMessage
+ }
+ hasError={errors.compositeDogCompositeToysDescription?.hasError}
+ ref={compositeDogCompositeToysDescriptionRef}
+ labelHidden={true}
+ {...getOverrideProps(
+ overrides,
+ \\"compositeDogCompositeToysDescription\\"
+ )}
+ >
+
+
+
+
+
+
+
+
+ );
+}
+"
+`;
+
+exports[`amplify form renderer tests datastore form tests custom form tests should render a create form for child of 1:m relationship 2`] = `
+"import * as React from \\"react\\";
+import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
+import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
+export declare type ValidationResponse = {
+ hasError: boolean;
+ errorMessage?: string;
+};
+export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
+export declare type CreateCompositeToyFormInputValues = {
+ kind?: string;
+ color?: string;
+ compositeDogCompositeToysName?: string;
+ compositeDogCompositeToysDescription?: string;
+};
+export declare type CreateCompositeToyFormValidationValues = {
+ kind?: ValidationFunction;
+ color?: ValidationFunction;
+ compositeDogCompositeToysName?: ValidationFunction;
+ compositeDogCompositeToysDescription?: ValidationFunction;
+};
+export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
+export declare type CreateCompositeToyFormOverridesProps = {
+ CreateCompositeToyFormGrid?: PrimitiveOverrideProps;
+ kind?: PrimitiveOverrideProps;
+ color?: PrimitiveOverrideProps;
+ compositeDogCompositeToysName?: PrimitiveOverrideProps;
+ compositeDogCompositeToysDescription?: PrimitiveOverrideProps;
+} & EscapeHatchProps;
+export declare type CreateCompositeToyFormProps = React.PropsWithChildren<{
+ overrides?: CreateCompositeToyFormOverridesProps | undefined | null;
+} & {
+ clearOnSuccess?: boolean;
+ onSubmit?: (fields: CreateCompositeToyFormInputValues) => CreateCompositeToyFormInputValues;
+ onSuccess?: (fields: CreateCompositeToyFormInputValues) => void;
+ onError?: (fields: CreateCompositeToyFormInputValues, errorMessage: string) => void;
+ onChange?: (fields: CreateCompositeToyFormInputValues) => CreateCompositeToyFormInputValues;
+ onValidate?: CreateCompositeToyFormValidationValues;
+} & React.CSSProperties>;
+export default function CreateCompositeToyForm(props: CreateCompositeToyFormProps): React.ReactElement;
+"
+`;
+
exports[`amplify form renderer tests datastore form tests custom form tests should render a create form for model with composite keys 1`] = `
"/* eslint-disable */
import * as React from \\"react\\";
@@ -7997,18 +8557,24 @@ export default function MyMemberForm(props) {
} = props;
const initialValues = {
name: \\"\\",
+ teamID: undefined,
Team: undefined,
};
const [name, setName] = React.useState(initialValues.name);
+ const [teamID, setTeamID] = React.useState(initialValues.teamID);
const [Team, setTeam] = React.useState(initialValues.Team);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
setName(initialValues.name);
+ setTeamID(initialValues.teamID);
+ setCurrentTeamIDValue(undefined);
setTeam(initialValues.Team);
setCurrentTeamValue(undefined);
setCurrentTeamDisplayValue(\\"\\");
setErrors({});
};
+ const [currentTeamIDValue, setCurrentTeamIDValue] = React.useState(undefined);
+ const teamIDRef = React.createRef();
const [currentTeamDisplayValue, setCurrentTeamDisplayValue] =
React.useState(\\"\\");
const [currentTeamValue, setCurrentTeamValue] = React.useState(undefined);
@@ -8030,6 +8596,7 @@ export default function MyMemberForm(props) {
};
const validations = {
name: [],
+ teamID: [{ type: \\"Required\\" }],
Team: [],
};
const runValidationTasks = async (
@@ -8058,6 +8625,7 @@ export default function MyMemberForm(props) {
event.preventDefault();
let modelFields = {
name,
+ teamID,
Team,
};
const validationResponses = await Promise.all(
@@ -8156,6 +8724,7 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name: value,
+ teamID,
Team,
};
const result = onChange(modelFields);
@@ -8178,6 +8747,61 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name,
+ teamID: value,
+ Team,
+ };
+ const result = onChange(modelFields);
+ value = result?.teamID ?? value;
+ }
+ setTeamID(value);
+ setCurrentTeamIDValue(undefined);
+ }}
+ currentFieldValue={currentTeamIDValue}
+ label={\\"Team id\\"}
+ items={teamID ? [teamID] : []}
+ hasError={errors.teamID?.hasError}
+ setFieldValue={setCurrentTeamIDValue}
+ inputFieldRef={teamIDRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: r?.id,
+ label: r?.id,
+ }))}
+ onSelect={({ id }) => {
+ setCurrentTeamIDValue(id);
+ }}
+ onClear={() => {
+ setCurrentTeamIDDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ if (errors.teamID?.hasError) {
+ runValidationTasks(\\"teamID\\", value);
+ }
+ setCurrentTeamIDValue(value);
+ }}
+ onBlur={() => runValidationTasks(\\"teamID\\", currentTeamIDValue)}
+ errorMessage={errors.teamID?.errorMessage}
+ hasError={errors.teamID?.hasError}
+ ref={teamIDRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"teamID\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ name,
+ teamID,
Team: value,
};
const result = onChange(modelFields);
@@ -8258,16 +8882,19 @@ export declare type ValidationResponse = {
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
export declare type MyMemberFormInputValues = {
name?: string;
+ teamID?: string;
Team?: Team0;
};
export declare type MyMemberFormValidationValues = {
name?: ValidationFunction;
+ teamID?: ValidationFunction;
Team?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
export declare type MyMemberFormOverridesProps = {
MyMemberFormGrid?: PrimitiveOverrideProps;
name?: PrimitiveOverrideProps;
+ teamID?: PrimitiveOverrideProps;
Team?: PrimitiveOverrideProps;
} & EscapeHatchProps;
export declare type MyMemberFormProps = React.PropsWithChildren<{
@@ -11891,16 +12518,20 @@ export default function MyMemberForm(props) {
} = props;
const initialValues = {
name: \\"\\",
+ teamID: undefined,
Team: undefined,
};
const [name, setName] = React.useState(initialValues.name);
+ const [teamID, setTeamID] = React.useState(initialValues.teamID);
const [Team, setTeam] = React.useState(initialValues.Team);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
const cleanValues = memberRecord
- ? { ...initialValues, ...memberRecord, Team }
+ ? { ...initialValues, ...memberRecord, teamID, Team }
: initialValues;
setName(cleanValues.name);
+ setTeamID(cleanValues.teamID);
+ setCurrentTeamIDValue(undefined);
setTeam(cleanValues.Team);
setCurrentTeamValue(undefined);
setCurrentTeamDisplayValue(\\"\\");
@@ -11911,12 +12542,16 @@ export default function MyMemberForm(props) {
const queryData = async () => {
const record = idProp ? await DataStore.query(Member, idProp) : member;
setMemberRecord(record);
+ const teamIDRecord = record ? await record.teamID : undefined;
+ setTeamID(teamIDRecord);
const TeamRecord = record ? await record.Team : undefined;
setTeam(TeamRecord);
};
queryData();
}, [idProp, member]);
- React.useEffect(resetStateValues, [memberRecord, Team]);
+ React.useEffect(resetStateValues, [memberRecord, teamID, Team]);
+ const [currentTeamIDValue, setCurrentTeamIDValue] = React.useState(undefined);
+ const teamIDRef = React.createRef();
const [currentTeamDisplayValue, setCurrentTeamDisplayValue] =
React.useState(\\"\\");
const [currentTeamValue, setCurrentTeamValue] = React.useState(undefined);
@@ -11938,6 +12573,7 @@ export default function MyMemberForm(props) {
};
const validations = {
name: [],
+ teamID: [{ type: \\"Required\\" }],
Team: [],
};
const runValidationTasks = async (
@@ -11966,6 +12602,7 @@ export default function MyMemberForm(props) {
event.preventDefault();
let modelFields = {
name,
+ teamID,
Team,
};
const validationResponses = await Promise.all(
@@ -12072,6 +12709,7 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name: value,
+ teamID,
Team,
};
const result = onChange(modelFields);
@@ -12094,6 +12732,62 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name,
+ teamID: value,
+ Team,
+ };
+ const result = onChange(modelFields);
+ value = result?.teamID ?? value;
+ }
+ setTeamID(value);
+ setCurrentTeamIDValue(undefined);
+ }}
+ currentFieldValue={currentTeamIDValue}
+ label={\\"Team id\\"}
+ items={teamID ? [teamID] : []}
+ hasError={errors.teamID?.hasError}
+ setFieldValue={setCurrentTeamIDValue}
+ inputFieldRef={teamIDRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: r?.id,
+ label: r?.id,
+ }))}
+ onSelect={({ id }) => {
+ setCurrentTeamIDValue(id);
+ }}
+ onClear={() => {
+ setCurrentTeamIDDisplayValue(\\"\\");
+ }}
+ defaultValue={teamID}
+ onChange={(e) => {
+ let { value } = e.target;
+ if (errors.teamID?.hasError) {
+ runValidationTasks(\\"teamID\\", value);
+ }
+ setCurrentTeamIDValue(value);
+ }}
+ onBlur={() => runValidationTasks(\\"teamID\\", currentTeamIDValue)}
+ errorMessage={errors.teamID?.errorMessage}
+ hasError={errors.teamID?.hasError}
+ ref={teamIDRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"teamID\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ name,
+ teamID,
Team: value,
};
const result = onChange(modelFields);
@@ -12175,16 +12869,19 @@ export declare type ValidationResponse = {
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
export declare type MyMemberFormInputValues = {
name?: string;
+ teamID?: string;
Team?: Team0;
};
export declare type MyMemberFormValidationValues = {
name?: ValidationFunction;
+ teamID?: ValidationFunction;
Team?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
export declare type MyMemberFormOverridesProps = {
MyMemberFormGrid?: PrimitiveOverrideProps;
name?: PrimitiveOverrideProps;
+ teamID?: PrimitiveOverrideProps;
Team?: PrimitiveOverrideProps;
} & EscapeHatchProps;
export declare type MyMemberFormProps = React.PropsWithChildren<{
@@ -17217,18 +17914,24 @@ export default function MyMemberForm(props) {
} = props;
const initialValues = {
name: \\"\\",
+ teamID: undefined,
Team: undefined,
};
const [name, setName] = React.useState(initialValues.name);
+ const [teamID, setTeamID] = React.useState(initialValues.teamID);
const [Team, setTeam] = React.useState(initialValues.Team);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
setName(initialValues.name);
+ setTeamID(initialValues.teamID);
+ setCurrentTeamIDValue(undefined);
setTeam(initialValues.Team);
setCurrentTeamValue(undefined);
setCurrentTeamDisplayValue(\\"\\");
setErrors({});
};
+ const [currentTeamIDValue, setCurrentTeamIDValue] = React.useState(undefined);
+ const teamIDRef = React.createRef();
const [currentTeamDisplayValue, setCurrentTeamDisplayValue] =
React.useState(\\"\\");
const [currentTeamValue, setCurrentTeamValue] = React.useState(undefined);
@@ -17250,6 +17953,7 @@ export default function MyMemberForm(props) {
};
const validations = {
name: [],
+ teamID: [{ type: \\"Required\\" }],
Team: [],
};
const runValidationTasks = async (
@@ -17278,6 +17982,7 @@ export default function MyMemberForm(props) {
event.preventDefault();
let modelFields = {
name,
+ teamID,
Team,
};
const validationResponses = await Promise.all(
@@ -17376,6 +18081,7 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name: value,
+ teamID,
Team,
};
const result = onChange(modelFields);
@@ -17398,6 +18104,61 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name,
+ teamID: value,
+ Team,
+ };
+ const result = onChange(modelFields);
+ value = result?.teamID ?? value;
+ }
+ setTeamID(value);
+ setCurrentTeamIDValue(undefined);
+ }}
+ currentFieldValue={currentTeamIDValue}
+ label={\\"Team id\\"}
+ items={teamID ? [teamID] : []}
+ hasError={errors.teamID?.hasError}
+ setFieldValue={setCurrentTeamIDValue}
+ inputFieldRef={teamIDRef}
+ defaultFieldValue={\\"\\"}
+ >
+ ({
+ id: r?.id,
+ label: r?.id,
+ }))}
+ onSelect={({ id }) => {
+ setCurrentTeamIDValue(id);
+ }}
+ onClear={() => {
+ setCurrentTeamIDDisplayValue(\\"\\");
+ }}
+ onChange={(e) => {
+ let { value } = e.target;
+ if (errors.teamID?.hasError) {
+ runValidationTasks(\\"teamID\\", value);
+ }
+ setCurrentTeamIDValue(value);
+ }}
+ onBlur={() => runValidationTasks(\\"teamID\\", currentTeamIDValue)}
+ errorMessage={errors.teamID?.errorMessage}
+ hasError={errors.teamID?.hasError}
+ ref={teamIDRef}
+ labelHidden={true}
+ {...getOverrideProps(overrides, \\"teamID\\")}
+ >
+
+ {
+ let value = items[0];
+ if (onChange) {
+ const modelFields = {
+ name,
+ teamID,
Team: value,
};
const result = onChange(modelFields);
@@ -17478,16 +18239,19 @@ export declare type ValidationResponse = {
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
export declare type MyMemberFormInputValues = {
name?: string;
+ teamID?: string;
Team?: Team0;
};
export declare type MyMemberFormValidationValues = {
name?: ValidationFunction;
+ teamID?: ValidationFunction;
Team?: ValidationFunction;
};
export declare type PrimitiveOverrideProps = Partial & React.DOMAttributes;
export declare type MyMemberFormOverridesProps = {
MyMemberFormGrid?: PrimitiveOverrideProps;
name?: PrimitiveOverrideProps;
+ teamID?: PrimitiveOverrideProps;
Team?: PrimitiveOverrideProps;
} & EscapeHatchProps;
export declare type MyMemberFormProps = React.PropsWithChildren<{
diff --git a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts
index a29af49fd..795b9b19d 100644
--- a/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts
+++ b/packages/codegen-ui-react/lib/__tests__/studio-ui-codegen-react-forms.test.ts
@@ -499,6 +499,18 @@ describe('amplify form renderer tests', () => {
expect(componentText).not.toContain('CompositeToys');
expect(componentText).not.toContain('CompositeVets');
});
+
+ it('should render a create form for child of 1:m relationship', () => {
+ const { componentText, declaration } = generateWithAmplifyFormRenderer(
+ 'forms/composite-toy-datastore-create',
+ 'datastore/composite-relationships',
+ undefined,
+ { isNonModelSupported: true, isRelationshipSupported: true },
+ );
+
+ expect(componentText).toMatchSnapshot();
+ expect(declaration).toMatchSnapshot();
+ });
});
});
});
diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
index b95419ab7..c6b2b8a73 100644
--- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
+++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/relationship.ts
@@ -16,7 +16,6 @@
import { CallExpression, factory, IfStatement, NodeFlags, SyntaxKind } from 'typescript';
import {
FieldConfigMetadata,
- GenericDataRelationshipType,
HasManyRelationshipType,
InternalError,
GenericDataModel,
@@ -30,11 +29,7 @@ import { isManyToManyRelationship } from './map-from-fieldConfigs';
import { extractModelAndKeys, getIDValueCallChain, getMatchEveryModelFieldCallExpression } from './model-values';
import { isModelDataType } from './render-checkers';
-export const buildRelationshipQuery = (
- relationship: GenericDataRelationshipType,
- importCollection: ImportCollection,
-) => {
- const { relatedModelName } = relationship;
+export const buildRelationshipQuery = (relatedModelName: string, importCollection: ImportCollection) => {
const itemsName = getRecordsName(relatedModelName);
const objectProperties = [
factory.createPropertyAssignment(factory.createIdentifier('type'), factory.createStringLiteral('collection')),
diff --git a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts
index e6e723317..7ceda070a 100644
--- a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts
+++ b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts
@@ -20,7 +20,6 @@ import {
FormDefinition,
generateFormDefinition,
GenericDataSchema,
- GenericDataRelationshipType,
handleCodegenErrors,
mapFormDefinitionToComponent,
mapFormMetadata,
@@ -518,7 +517,7 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
// Add value state and ref array type fields in ArrayField wrapper
- const relationshipCollection: GenericDataRelationshipType[] = [];
+ const relatedModelNames: Set = new Set();
Object.entries(formMetadata.fieldConfigs).forEach(([field, fieldConfig]) => {
const { sanitizedFieldName, componentType, dataType, relationship } = fieldConfig;
@@ -562,8 +561,8 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
);
}
- if (relationship) {
- relationshipCollection.push(relationship);
+ if (relationship && !relatedModelNames.has(relationship.relatedModelName)) {
+ relatedModelNames.add(relationship.relatedModelName);
}
});
@@ -590,10 +589,12 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
model: Author,
}).items;
*/
- if (relationshipCollection.length) {
+ if (relatedModelNames.size) {
this.importCollection.addMappedImport(ImportValue.USE_DATA_STORE_BINDING);
statements.push(
- ...relationshipCollection.map((relationship) => buildRelationshipQuery(relationship, this.importCollection)),
+ ...[...relatedModelNames].map((relatedModelName) =>
+ buildRelationshipQuery(relatedModelName, this.importCollection),
+ ),
);
}
diff --git a/packages/codegen-ui/example-schemas/forms/composite-toy-datastore-create.json b/packages/codegen-ui/example-schemas/forms/composite-toy-datastore-create.json
new file mode 100644
index 000000000..279b623a0
--- /dev/null
+++ b/packages/codegen-ui/example-schemas/forms/composite-toy-datastore-create.json
@@ -0,0 +1,12 @@
+{
+ "name": "CreateCompositeToyForm",
+ "dataType": {
+ "dataSourceType": "DataStore",
+ "dataTypeName": "CompositeToy"
+ },
+ "formActionType": "create",
+ "fields": {},
+ "sectionalElements": {},
+ "style": {},
+ "cta": {}
+}
\ No newline at end of file
diff --git a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts
index f0631c0b1..9deab6037 100644
--- a/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts
+++ b/packages/codegen-ui/lib/__tests__/generate-form-definition/helpers/model-fields-configs.test.ts
@@ -398,7 +398,12 @@ describe('mapModelFieldsConfigs', () => {
},
};
- const modelFieldsConfigs = mapModelFieldsConfigs({ dataTypeName: 'Dog', formDefinition, dataSchema });
+ const modelFieldsConfigs = mapModelFieldsConfigs({
+ dataTypeName: 'Dog',
+ formDefinition,
+ dataSchema,
+ featureFlags: { isRelationshipSupported: true },
+ });
expect(formDefinition.elementMatrix).toStrictEqual([]);
expect(modelFieldsConfigs).toStrictEqual({
@@ -423,6 +428,139 @@ describe('mapModelFieldsConfigs', () => {
});
});
+ it('should add not-model type relationship fields to configs and to matrix if it is hasMany index', () => {
+ const formDefinition: FormDefinition = getBasicFormDefinition();
+
+ const dataSchema: GenericDataSchema = {
+ dataSourceType: 'DataStore',
+ enums: {},
+ nonModels: {},
+ models: {
+ Owner: {
+ primaryKeys: ['id'],
+ fields: {},
+ },
+ CompositeDog: {
+ primaryKeys: ['name', 'description'],
+ fields: {
+ name: {
+ dataType: 'ID',
+ required: true,
+ readOnly: false,
+ isArray: false,
+ },
+ description: {
+ dataType: 'String',
+ required: true,
+ readOnly: false,
+ isArray: false,
+ },
+ CompositeToys: {
+ dataType: {
+ model: 'CompositeToy',
+ },
+ required: false,
+ readOnly: false,
+ isArray: true,
+ relationship: {
+ type: 'HAS_MANY',
+ relatedModelName: 'CompositeToy',
+ relatedModelFields: ['compositeDogCompositeToysName', 'compositeDogCompositeToysDescription'],
+ },
+ },
+ },
+ },
+ CompositeToy: {
+ fields: {
+ kind: {
+ dataType: 'ID',
+ required: true,
+ readOnly: false,
+ isArray: false,
+ },
+ color: {
+ dataType: 'String',
+ required: true,
+ readOnly: false,
+ isArray: false,
+ },
+ compositeDogCompositeToysName: {
+ dataType: 'ID',
+ required: false,
+ readOnly: false,
+ isArray: false,
+ relationship: {
+ type: 'HAS_ONE',
+ relatedModelName: 'CompositeDog',
+ isHasManyIndex: true,
+ },
+ },
+ compositeDogCompositeToysDescription: {
+ dataType: 'String',
+ required: false,
+ readOnly: false,
+ isArray: false,
+ relationship: {
+ type: 'HAS_ONE',
+ relatedModelName: 'CompositeDog',
+ isHasManyIndex: true,
+ },
+ },
+ },
+ primaryKeys: ['kind', 'color'],
+ },
+ },
+ };
+
+ const modelFieldsConfigs = mapModelFieldsConfigs({
+ dataTypeName: 'CompositeToy',
+ formDefinition,
+ dataSchema,
+ featureFlags: { isRelationshipSupported: true },
+ });
+
+ expect(formDefinition.elementMatrix).toStrictEqual([
+ ['kind'],
+ ['color'],
+ ['compositeDogCompositeToysName'],
+ ['compositeDogCompositeToysDescription'],
+ ]);
+ expect(modelFieldsConfigs.compositeDogCompositeToysName).toStrictEqual({
+ label: 'Composite dog composite toys name',
+ dataType: 'ID',
+ inputType: {
+ type: 'Autocomplete',
+ required: false,
+ readOnly: false,
+ name: 'compositeDogCompositeToysName',
+ value: 'compositeDogCompositeToysName',
+ isArray: false,
+ valueMappings: {
+ values: [{ value: { bindingProperties: { property: 'CompositeDog', field: 'name' } } }],
+ bindingProperties: { CompositeDog: { type: 'Data', bindingProperties: { model: 'CompositeDog' } } },
+ },
+ },
+ relationship: { type: 'HAS_ONE', relatedModelName: 'CompositeDog', isHasManyIndex: true },
+ });
+ expect(modelFieldsConfigs.compositeDogCompositeToysDescription).toStrictEqual({
+ label: 'Composite dog composite toys description',
+ dataType: 'String',
+ inputType: {
+ type: 'Autocomplete',
+ required: false,
+ readOnly: false,
+ name: 'compositeDogCompositeToysDescription',
+ value: 'compositeDogCompositeToysDescription',
+ isArray: false,
+ valueMappings: {
+ values: [{ value: { bindingProperties: { property: 'CompositeDog', field: 'description' } } }],
+ bindingProperties: { CompositeDog: { type: 'Data', bindingProperties: { model: 'CompositeDog' } } },
+ },
+ },
+ relationship: { type: 'HAS_ONE', relatedModelName: 'CompositeDog', isHasManyIndex: true },
+ });
+ });
+
it('should add nonModel field to matrix if nonModel enabled', () => {
const formDefinition: FormDefinition = getBasicFormDefinition();
diff --git a/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts b/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts
index b0e9b79a6..f9139c28b 100644
--- a/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts
+++ b/packages/codegen-ui/lib/__tests__/generic-from-datastore.test.ts
@@ -114,6 +114,7 @@ describe('getGenericFromDataStore', () => {
expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Owner',
+ isHasManyIndex: true,
});
});
@@ -175,6 +176,7 @@ describe('getGenericFromDataStore', () => {
expect(genericSchema.models.Dog.fields.ownerID.relationship).toStrictEqual({
type: 'HAS_ONE',
relatedModelName: 'Owner',
+ isHasManyIndex: true,
});
});
diff --git a/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts b/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts
index bfa2d926c..2cc12c658 100644
--- a/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts
+++ b/packages/codegen-ui/lib/generate-form-definition/helpers/model-fields-configs.ts
@@ -34,6 +34,41 @@ import { ExtendedStudioGenericFieldConfig } from '../../types/form/form-definiti
import { StudioFormInputFieldProperty } from '../../types/form/input-config';
import { FIELD_TYPE_MAP } from './field-type-map';
+function extractCorrespondingKey({
+ thisModel,
+ relatedModel,
+ relationshipFieldName,
+}: {
+ thisModel: GenericDataModel;
+ relatedModel: GenericDataModel;
+ relationshipFieldName: string;
+}): string {
+ const relationshipField = thisModel.fields[relationshipFieldName];
+ if (
+ relationshipField.relationship &&
+ 'isHasManyIndex' in relationshipField.relationship &&
+ relationshipField.relationship.isHasManyIndex
+ ) {
+ const correspondingFieldTuple = Object.entries(relatedModel.fields).find(
+ ([, field]) =>
+ field.relationship?.type === 'HAS_MANY' &&
+ field.relationship?.relatedModelFields.includes(relationshipFieldName),
+ );
+ if (correspondingFieldTuple) {
+ const correspondingField = correspondingFieldTuple[1].relationship;
+ if (correspondingField?.type === 'HAS_MANY') {
+ const indexOfKey = correspondingField.relatedModelFields.indexOf(relationshipFieldName);
+ if (indexOfKey !== -1) {
+ return relatedModel.primaryKeys[indexOfKey];
+ }
+ }
+ }
+ }
+
+ // TODO: support other types
+ return relationshipFieldName;
+}
+
export function getFieldTypeMapKey(field: GenericDataField): FieldTypeMapKeys {
if (typeof field.dataType === 'object' && 'enum' in field.dataType) {
return 'Enum';
@@ -96,11 +131,13 @@ function getModelDisplayValue({
}
function getValueMappings({
+ dataTypeName,
fieldName,
field,
enums,
allModels,
}: {
+ dataTypeName: string;
fieldName: string;
field: GenericDataField;
enums: GenericDataSchema['enums'];
@@ -126,8 +163,16 @@ function getValueMappings({
const modelName = field.relationship.relatedModelName;
const relatedModel = allModels[modelName];
const isModelType = typeof field.dataType === 'object' && 'model' in field.dataType;
- // if model, store all keys; else, store field as key
- const keys = isModelType ? relatedModel.primaryKeys : [fieldName];
+ // if model, store all keys; else, store corresponding primary key
+ const keys = isModelType
+ ? relatedModel.primaryKeys
+ : [
+ extractCorrespondingKey({
+ thisModel: allModels[dataTypeName],
+ relatedModel,
+ relationshipFieldName: fieldName,
+ }),
+ ];
const values: StudioFormValueMappings['values'] = keys.map((key) => ({
value: { bindingProperties: { property: modelName, field: key } },
}));
@@ -145,11 +190,13 @@ function getValueMappings({
}
export function getFieldConfigFromModelField({
+ dataTypeName,
fieldName,
field,
dataSchema,
setReadOnly,
}: {
+ dataTypeName: string;
fieldName: string;
field: GenericDataField;
dataSchema: GenericDataSchema;
@@ -197,7 +244,13 @@ export function getFieldConfigFromModelField({
config.inputType.placeholder = `Search ${field.relationship.relatedModelName}`;
}
- const valueMappings = getValueMappings({ fieldName, field, enums: dataSchema.enums, allModels: dataSchema.models });
+ const valueMappings = getValueMappings({
+ dataTypeName,
+ fieldName,
+ field,
+ enums: dataSchema.enums,
+ allModels: dataSchema.models,
+ });
if (valueMappings) {
config.inputType.valueMappings = valueMappings;
}
@@ -234,7 +287,9 @@ export function mapModelFieldsConfigs({
field.readOnly ||
(fieldName === 'id' && field.dataType === 'ID' && field.required) ||
!checkIsSupportedAsFormField(field, featureFlags) ||
- (field.relationship && !(typeof field.dataType === 'object' && 'model' in field.dataType));
+ (field.relationship &&
+ !(typeof field.dataType === 'object' && 'model' in field.dataType) &&
+ !('isHasManyIndex' in field.relationship && field.relationship.isHasManyIndex));
if (!isAutoExcludedField) {
formDefinition.elementMatrix.push([fieldName]);
@@ -243,6 +298,7 @@ export function mapModelFieldsConfigs({
const isPrimaryKey = model.primaryKeys.includes(fieldName);
modelFieldsConfigs[fieldName] = getFieldConfigFromModelField({
+ dataTypeName,
fieldName,
field,
dataSchema,
diff --git a/packages/codegen-ui/lib/generic-from-datastore.ts b/packages/codegen-ui/lib/generic-from-datastore.ts
index 439ee904e..6f4ef3856 100644
--- a/packages/codegen-ui/lib/generic-from-datastore.ts
+++ b/packages/codegen-ui/lib/generic-from-datastore.ts
@@ -128,6 +128,7 @@ export function getGenericFromDataStore(dataStoreSchema: DataStoreSchema): Gener
addRelationship(fieldsWithImplicitRelationships, relatedModelName, associatedFieldName, {
type: 'HAS_ONE',
relatedModelName: model.name,
+ isHasManyIndex: true,
});
}
});
diff --git a/packages/codegen-ui/lib/types/data.ts b/packages/codegen-ui/lib/types/data.ts
index 5b2502edc..5b0ed0564 100644
--- a/packages/codegen-ui/lib/types/data.ts
+++ b/packages/codegen-ui/lib/types/data.ts
@@ -44,6 +44,7 @@ export type HasManyRelationshipType = {
export type HasOneRelationshipType = {
type: 'HAS_ONE';
associatedFields?: string[];
+ isHasManyIndex?: boolean;
} & CommonRelationshipType;
export type BelongsToRelationshipType = {
diff --git a/packages/test-generator/integration-test-templates/cypress/e2e/generate-spec.cy.ts b/packages/test-generator/integration-test-templates/cypress/e2e/generate-spec.cy.ts
index fefb6a275..9bcf038cd 100644
--- a/packages/test-generator/integration-test-templates/cypress/e2e/generate-spec.cy.ts
+++ b/packages/test-generator/integration-test-templates/cypress/e2e/generate-spec.cy.ts
@@ -37,6 +37,7 @@ const EXPECTED_SUCCESSFUL_CASES = new Set([
'DataStoreFormCreateCPKTeacher',
'DataStoreFormUpdateCompositeDog',
'DataStoreFormCreateCompositeDog',
+ 'DataStoreFormUpdateCompositeToy',
'ComponentWithDataBindingWithPredicate',
'ComponentWithDataBindingWithoutPredicate',
'ComponentWithSimplePropertyBinding',
diff --git a/packages/test-generator/integration-test-templates/cypress/e2e/update-form-spec.cy.ts b/packages/test-generator/integration-test-templates/cypress/e2e/update-form-spec.cy.ts
index 3df46e79e..d680bf5ef 100644
--- a/packages/test-generator/integration-test-templates/cypress/e2e/update-form-spec.cy.ts
+++ b/packages/test-generator/integration-test-templates/cypress/e2e/update-form-spec.cy.ts
@@ -205,4 +205,31 @@ describe('UpdateForms', () => {
});
});
});
+
+ // this model is m in 1:m
+ describe('DataStoreFormUpdateCompositeToy', () => {
+ beforeEach(() => {
+ cy.reload();
+ });
+ it('should update indices used for 1:m relationships', () => {
+ cy.get('#dataStoreFormUpdateCompositeToy').within(() => {
+ getArrayFieldButtonByLabel('Composite dog composite toys name').click();
+ typeInAutocomplete('Yundoo{downArrow}{enter}');
+ clickAddToArray();
+
+ getArrayFieldButtonByLabel('Composite dog composite toys description').click();
+ typeInAutocomplete('tiny but mighty{downArrow}{enter}');
+ clickAddToArray();
+
+ cy.contains('Submit').click();
+
+ cy.contains(/chew/).then((recordElement: JQuery) => {
+ const record = JSON.parse(recordElement.text());
+
+ expect(record.compositeDogCompositeToysName).to.equal('Yundoo');
+ expect(record.compositeDogCompositeToysDescription).to.equal('tiny but mighty');
+ });
+ });
+ });
+ });
});
diff --git a/packages/test-generator/integration-test-templates/src/UpdateFormTests.tsx b/packages/test-generator/integration-test-templates/src/UpdateFormTests.tsx
index 86b343393..b421bde84 100644
--- a/packages/test-generator/integration-test-templates/src/UpdateFormTests.tsx
+++ b/packages/test-generator/integration-test-templates/src/UpdateFormTests.tsx
@@ -21,6 +21,7 @@ import {
DataStoreFormUpdateAllSupportedFormFields,
DataStoreFormUpdateCompositeDog,
DataStoreFormUpdateCPKTeacher,
+ DataStoreFormUpdateCompositeToy,
} from './ui-components'; // eslint-disable-line import/extensions, max-len
import {
Owner,
@@ -266,6 +267,8 @@ export default function UpdateFormTests() {
const [compositeDogRecordString, setCompositeDogRecordString] = useState('');
const initializeStarted = useRef(false);
+ const [compositeToyRecord, setCompositeToyRecord] = useState();
+ const [compositeToyRecordString, setCompositeToyRecordString] = useState('');
useEffect(() => {
const initializeTestState = async () => {
if (initializeStarted.current) {
@@ -279,6 +282,7 @@ export default function UpdateFormTests() {
initializeCPKTeacherTestData({ setCPKTeacherId }),
initializeCompositeDogTestData({ setCompositeDogRecord }),
]);
+ setCompositeToyRecord(await DataStore.query(CompositeToy, { kind: 'chew', color: 'red' }));
setInitialized(true);
};
@@ -375,6 +379,18 @@ export default function UpdateFormTests() {
/>
{compositeDogRecordString}
+ DataStore Form - UpdateCompositeToy
+
+ {
+ const record = await DataStore.query(CompositeToy, { kind: 'chew', color: 'red' });
+
+ setCompositeToyRecordString(JSON.stringify(record));
+ }}
+ />
+ {compositeToyRecordString}
+
);
}
diff --git a/packages/test-generator/lib/forms/datastore-form-update-composite-toy.json b/packages/test-generator/lib/forms/datastore-form-update-composite-toy.json
new file mode 100644
index 000000000..d7a79104f
--- /dev/null
+++ b/packages/test-generator/lib/forms/datastore-form-update-composite-toy.json
@@ -0,0 +1,13 @@
+{
+ "id": "kdjfskdfddj",
+ "name": "DataStoreFormUpdateCompositeToy",
+ "dataType": {
+ "dataSourceType": "DataStore",
+ "dataTypeName": "CompositeToy"
+ },
+ "formActionType": "update",
+ "fields": {},
+ "sectionalElements": {},
+ "style": {},
+ "cta": {}
+}
\ No newline at end of file
diff --git a/packages/test-generator/lib/forms/index.ts b/packages/test-generator/lib/forms/index.ts
index 8e4c02644..9801e5cf7 100644
--- a/packages/test-generator/lib/forms/index.ts
+++ b/packages/test-generator/lib/forms/index.ts
@@ -24,3 +24,4 @@ export { default as DataStoreFormUpdateCPKTeacher } from './datastore-form-updat
export { default as DataStoreFormUpdateCompositeDog } from './datastore-form-update-composite-dog.json';
export { default as DataStoreFormCreateCPKTeacher } from './datastore-form-create-cpk-teacher.json';
export { default as DataStoreFormCreateCompositeDog } from './datastore-form-create-composite-dog.json';
+export { default as DataStoreFormUpdateCompositeToy } from './datastore-form-update-composite-toy.json';