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 8e3b3ccb4..a0eaa4257 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
@@ -3445,7 +3445,7 @@ exports[`amplify form renderer tests datastore form tests should generate a crea
"/* eslint-disable */
import * as React from \\"react\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import { Member, Team } from \\"../models\\";
+import { Member, Team as Team0 } from \\"../models\\";
import {
getOverrideProps,
useDataStoreBinding,
@@ -3622,14 +3622,14 @@ export default function MyMemberForm(props) {
} = props;
const initialValues = {
name: undefined,
- team: undefined,
+ Team: undefined,
};
const [name, setName] = React.useState(initialValues.name);
- const [team, setTeam] = React.useState(initialValues.team);
+ const [Team, setTeam] = React.useState(initialValues.Team);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
setName(initialValues.name);
- setTeam(initialValues.team);
+ setTeam(initialValues.Team);
setCurrentTeamValue(undefined);
setCurrentTeamDisplayValue(\\"\\");
setErrors({});
@@ -3637,17 +3637,17 @@ export default function MyMemberForm(props) {
const [currentTeamDisplayValue, setCurrentTeamDisplayValue] =
React.useState(\\"\\");
const [currentTeamValue, setCurrentTeamValue] = React.useState(undefined);
- const teamRef = React.createRef();
+ const TeamRef = React.createRef();
const teamRecords = useDataStoreBinding({
type: \\"collection\\",
- model: Team,
+ model: Team0,
}).items;
const getDisplayValue = {
- team: (record) => record?.name,
+ Team: (record) => record?.name,
};
const validations = {
name: [],
- team: [],
+ Team: [],
};
const runValidationTasks = async (
fieldName,
@@ -3675,7 +3675,7 @@ export default function MyMemberForm(props) {
event.preventDefault();
let modelFields = {
name,
- team,
+ Team,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
@@ -3761,7 +3761,7 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name: value,
- team,
+ Team,
};
const result = onChange(modelFields);
value = result?.name ?? value;
@@ -3783,10 +3783,10 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name,
- team: value,
+ Team: value,
};
const result = onChange(modelFields);
- value = result?.team ?? value;
+ value = result?.Team ?? value;
}
setTeam(value);
setCurrentTeamValue(undefined);
@@ -3794,11 +3794,11 @@ export default function MyMemberForm(props) {
}}
currentFieldValue={currentTeamValue}
label={\\"Team Label\\"}
- items={team ? [team] : []}
- hasError={errors.team?.hasError}
- getBadgeText={getDisplayValue.team}
+ items={Team ? [Team] : []}
+ hasError={errors.Team?.hasError}
+ getBadgeText={getDisplayValue.Team}
setFieldValue={setCurrentTeamDisplayValue}
- inputFieldRef={teamRef}
+ inputFieldRef={TeamRef}
defaultFieldValue={\\"\\"}
>
({
id: r.id,
- label: getDisplayValue.team?.(r) ?? r.id,
+ label: getDisplayValue.Team?.(r) ?? r.id,
}))}
onSelect={({ id, label }) => {
setCurrentTeamValue(teamRecords.find((r) => r.id === id));
@@ -3819,17 +3819,17 @@ export default function MyMemberForm(props) {
}}
onChange={(e) => {
let { value } = e.target;
- if (errors.team?.hasError) {
- runValidationTasks(\\"team\\", value);
+ if (errors.Team?.hasError) {
+ runValidationTasks(\\"Team\\", value);
}
setCurrentTeamDisplayValue(value);
setCurrentTeamValue(undefined);
}}
- onBlur={() => runValidationTasks(\\"team\\", team)}
- errorMessage={errors.team?.errorMessage}
- hasError={errors.team?.hasError}
- ref={teamRef}
- {...getOverrideProps(overrides, \\"team\\")}
+ onBlur={() => runValidationTasks(\\"Team\\", Team)}
+ errorMessage={errors.Team?.errorMessage}
+ hasError={errors.Team?.hasError}
+ ref={TeamRef}
+ {...getOverrideProps(overrides, \\"Team\\")}
>
@@ -3840,7 +3840,7 @@ export default function MyMemberForm(props) {
exports[`amplify form renderer tests datastore form tests should generate a create form with belongsTo relationship 2`] = `
"import * as React from \\"react\\";
-import { Team } from \\"../models\\";
+import { Team as Team0 } from \\"../models\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
export declare type ValidationResponse = {
@@ -3850,17 +3850,17 @@ export declare type ValidationResponse = {
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
export declare type MyMemberFormInputValues = {
name?: string;
- team?: Team;
+ Team?: Team0;
};
export declare type MyMemberFormValidationValues = {
name?: ValidationFunction;
- team?: ValidationFunction;
+ Team?: ValidationFunction;
};
export declare type FormProps = Partial & React.DOMAttributes;
export declare type MyMemberFormOverridesProps = {
MyMemberFormGrid?: FormProps;
name?: FormProps;
- team?: FormProps;
+ Team?: FormProps;
} & EscapeHatchProps;
export declare type MyMemberFormProps = React.PropsWithChildren<{
overrides?: MyMemberFormOverridesProps | undefined | null;
@@ -9575,7 +9575,7 @@ exports[`amplify form renderer tests datastore form tests should use proper fiel
"/* eslint-disable */
import * as React from \\"react\\";
import { fetchByPath, validateField } from \\"./utils\\";
-import { Member, Team } from \\"../models\\";
+import { Member, Team as Team0 } from \\"../models\\";
import {
getOverrideProps,
useDataStoreBinding,
@@ -9752,14 +9752,14 @@ export default function MyMemberForm(props) {
} = props;
const initialValues = {
name: undefined,
- team: undefined,
+ Team: undefined,
};
const [name, setName] = React.useState(initialValues.name);
- const [team, setTeam] = React.useState(initialValues.team);
+ const [Team, setTeam] = React.useState(initialValues.Team);
const [errors, setErrors] = React.useState({});
const resetStateValues = () => {
setName(initialValues.name);
- setTeam(initialValues.team);
+ setTeam(initialValues.Team);
setCurrentTeamValue(undefined);
setCurrentTeamDisplayValue(\\"\\");
setErrors({});
@@ -9767,17 +9767,17 @@ export default function MyMemberForm(props) {
const [currentTeamDisplayValue, setCurrentTeamDisplayValue] =
React.useState(\\"\\");
const [currentTeamValue, setCurrentTeamValue] = React.useState(undefined);
- const teamRef = React.createRef();
+ const TeamRef = React.createRef();
const teamRecords = useDataStoreBinding({
type: \\"collection\\",
- model: Team,
+ model: Team0,
}).items;
const getDisplayValue = {
- team: (record) => record?.name,
+ Team: (record) => record?.name,
};
const validations = {
name: [],
- team: [],
+ Team: [],
};
const runValidationTasks = async (
fieldName,
@@ -9805,7 +9805,7 @@ export default function MyMemberForm(props) {
event.preventDefault();
let modelFields = {
name,
- team,
+ Team,
};
const validationResponses = await Promise.all(
Object.keys(validations).reduce((promises, fieldName) => {
@@ -9891,7 +9891,7 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name: value,
- team,
+ Team,
};
const result = onChange(modelFields);
value = result?.name ?? value;
@@ -9913,10 +9913,10 @@ export default function MyMemberForm(props) {
if (onChange) {
const modelFields = {
name,
- team: value,
+ Team: value,
};
const result = onChange(modelFields);
- value = result?.team ?? value;
+ value = result?.Team ?? value;
}
setTeam(value);
setCurrentTeamValue(undefined);
@@ -9924,11 +9924,11 @@ export default function MyMemberForm(props) {
}}
currentFieldValue={currentTeamValue}
label={\\"Team Label\\"}
- items={team ? [team] : []}
- hasError={errors.team?.hasError}
- getBadgeText={getDisplayValue.team}
+ items={Team ? [Team] : []}
+ hasError={errors.Team?.hasError}
+ getBadgeText={getDisplayValue.Team}
setFieldValue={setCurrentTeamDisplayValue}
- inputFieldRef={teamRef}
+ inputFieldRef={TeamRef}
defaultFieldValue={\\"\\"}
>
({
id: r.id,
- label: getDisplayValue.team?.(r) ?? r.id,
+ label: getDisplayValue.Team?.(r) ?? r.id,
}))}
onSelect={({ id, label }) => {
setCurrentTeamValue(teamRecords.find((r) => r.id === id));
@@ -9949,17 +9949,17 @@ export default function MyMemberForm(props) {
}}
onChange={(e) => {
let { value } = e.target;
- if (errors.team?.hasError) {
- runValidationTasks(\\"team\\", value);
+ if (errors.Team?.hasError) {
+ runValidationTasks(\\"Team\\", value);
}
setCurrentTeamDisplayValue(value);
setCurrentTeamValue(undefined);
}}
- onBlur={() => runValidationTasks(\\"team\\", team)}
- errorMessage={errors.team?.errorMessage}
- hasError={errors.team?.hasError}
- ref={teamRef}
- {...getOverrideProps(overrides, \\"team\\")}
+ onBlur={() => runValidationTasks(\\"Team\\", Team)}
+ errorMessage={errors.Team?.errorMessage}
+ hasError={errors.Team?.hasError}
+ ref={TeamRef}
+ {...getOverrideProps(overrides, \\"Team\\")}
>
@@ -9970,7 +9970,7 @@ export default function MyMemberForm(props) {
exports[`amplify form renderer tests datastore form tests should use proper field overrides for belongsTo relationship 2`] = `
"import * as React from \\"react\\";
-import { Team } from \\"../models\\";
+import { Team as Team0 } from \\"../models\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
import { AutocompleteProps, GridProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
export declare type ValidationResponse = {
@@ -9980,17 +9980,17 @@ export declare type ValidationResponse = {
export declare type ValidationFunction = (value: T, validationResponse: ValidationResponse) => ValidationResponse | Promise;
export declare type MyMemberFormInputValues = {
name?: string;
- team?: Team;
+ Team?: Team0;
};
export declare type MyMemberFormValidationValues = {
name?: ValidationFunction;
- team?: ValidationFunction;
+ Team?: ValidationFunction;
};
export declare type FormProps = Partial & React.DOMAttributes;
export declare type MyMemberFormOverridesProps = {
MyMemberFormGrid?: FormProps;
name?: FormProps;
- team?: FormProps;
+ Team?: FormProps;
} & EscapeHatchProps;
export declare type MyMemberFormProps = React.PropsWithChildren<{
overrides?: MyMemberFormOverridesProps | undefined | null;
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 d8873da6a..1b70fa7d4 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
@@ -64,7 +64,7 @@ describe('amplify form renderer tests', () => {
'datastore/project-team-model',
);
// check nested model is imported
- expect(componentText).toContain('import { Member, Team } from "../models";');
+ expect(componentText).toContain('import { Member, Team as Team0 } from "../models";');
// check binding call is generated
expect(componentText).toContain('const teamRecords = useDataStoreBinding({');
@@ -81,7 +81,7 @@ describe('amplify form renderer tests', () => {
// Check that custom field label is working as expected
expect(componentText).toContain('Team Label');
// Check that Autocomplete custom display value is set
- expect(componentText).toContain('team: (record) => record?.name');
+ expect(componentText).toContain('Team: (record) => record?.name');
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 14d78e2c2..3d8048d24 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
@@ -17,13 +17,20 @@ import { factory, NodeFlags, SyntaxKind } from 'typescript';
import { FieldConfigMetadata, GenericDataRelationshipType, HasManyRelationshipType } from '@aws-amplify/codegen-ui';
import { getRecordsName } from './form-state';
import { buildBaseCollectionVariableStatement } from '../../react-studio-template-renderer-helper';
+import { ImportCollection, ImportSource } from '../../imports';
-export const buildRelationshipQuery = (relationship: GenericDataRelationshipType) => {
+export const buildRelationshipQuery = (
+ relationship: GenericDataRelationshipType,
+ importCollection: ImportCollection,
+) => {
const { relatedModelName } = relationship;
const itemsName = getRecordsName(relatedModelName);
const objectProperties = [
factory.createPropertyAssignment(factory.createIdentifier('type'), factory.createStringLiteral('collection')),
- factory.createPropertyAssignment(factory.createIdentifier('model'), factory.createIdentifier(relatedModelName)),
+ factory.createPropertyAssignment(
+ factory.createIdentifier('model'),
+ factory.createIdentifier(importCollection.getMappedAlias(ImportSource.LOCAL_MODELS, relatedModelName)),
+ ),
];
return buildBaseCollectionVariableStatement(
itemsName,
diff --git a/packages/codegen-ui-react/lib/forms/form-renderer-helper/type-helper.ts b/packages/codegen-ui-react/lib/forms/form-renderer-helper/type-helper.ts
index 9215f6c60..dd5cc761d 100644
--- a/packages/codegen-ui-react/lib/forms/form-renderer-helper/type-helper.ts
+++ b/packages/codegen-ui-react/lib/forms/form-renderer-helper/type-helper.ts
@@ -67,8 +67,8 @@ const getTypeNode = ({ componentType, dataType, isArray, isValidation, importCol
if (dataType && typeof dataType === 'object' && 'model' in dataType) {
const modelName = dataType.model;
- importCollection?.addImport(ImportSource.LOCAL_MODELS, modelName);
- typeNode = factory.createTypeReferenceNode(factory.createIdentifier(modelName));
+ const aliasedModel = importCollection?.addImport(ImportSource.LOCAL_MODELS, modelName);
+ typeNode = factory.createTypeReferenceNode(factory.createIdentifier(aliasedModel || modelName));
}
if (isValidation) {
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 fb7d99208..e04efb5a3 100644
--- a/packages/codegen-ui-react/lib/forms/react-form-renderer.ts
+++ b/packages/codegen-ui-react/lib/forms/react-form-renderer.ts
@@ -271,7 +271,6 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
private renderBindingPropsType(): TypeAliasDeclaration[] {
const {
name: formName,
- formActionType,
dataType: { dataSourceType, dataTypeName },
} = this.component;
const fieldConfigs = this.componentMetadata.formMetadata?.fieldConfigs ?? {};
@@ -297,19 +296,19 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
this.importCollection.addMappedImport(ImportValue.ESCAPE_HATCH_PROPS);
let modelName = dataTypeName;
- if (dataSourceType === 'DataStore' && formActionType === 'update') {
- // add model import for datastore type
- if (dataSourceType === 'DataStore') {
- this.requiredDataModels.push(dataTypeName);
- modelName = this.importCollection.addImport(ImportSource.LOCAL_MODELS, dataTypeName);
- }
+
+ // add model import for datastore type
+ if (dataSourceType === 'DataStore') {
+ this.requiredDataModels.push(dataTypeName);
+ modelName = this.importCollection.addImport(ImportSource.LOCAL_MODELS, dataTypeName);
}
+
return [
validationResponseType,
validationFunctionType,
// pass in importCollection once to collect models to import
generateFieldTypes(formName, 'input', fieldConfigs, this.importCollection),
- generateFieldTypes(formName, 'validation', fieldConfigs),
+ generateFieldTypes(formName, 'validation', fieldConfigs, this.importCollection),
formOverrideProp,
overrideTypeAliasDeclaration,
factory.createTypeAliasDeclaration(
@@ -512,6 +511,16 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
}
});
+ const { validationsObject, dataTypesMap, displayValueObject, modelsToImport, usesArrayField } = mapFromFieldConfigs(
+ formMetadata.fieldConfigs,
+ );
+
+ this.shouldRenderArrayField = usesArrayField;
+
+ this.requiredDataModels.push(...modelsToImport);
+
+ modelsToImport.forEach((model) => this.importCollection.addImport(ImportSource.LOCAL_MODELS, model));
+
// datastore relationship query
/**
const authorRecords = useDataStoreBinding({
@@ -521,19 +530,11 @@ export abstract class ReactFormTemplateRenderer extends StudioTemplateRenderer<
*/
if (relationshipCollection.length) {
this.importCollection.addMappedImport(ImportValue.USE_DATA_STORE_BINDING);
- statements.push(...relationshipCollection.map((relationship) => buildRelationshipQuery(relationship)));
+ statements.push(
+ ...relationshipCollection.map((relationship) => buildRelationshipQuery(relationship, this.importCollection)),
+ );
}
- const { validationsObject, dataTypesMap, displayValueObject, modelsToImport, usesArrayField } = mapFromFieldConfigs(
- formMetadata.fieldConfigs,
- );
-
- this.shouldRenderArrayField = usesArrayField;
-
- this.requiredDataModels.push(...modelsToImport);
-
- modelsToImport.forEach((model) => this.importCollection.addImport(ImportSource.LOCAL_MODELS, model));
-
if (displayValueObject) {
statements.push(displayValueObject);
}
diff --git a/packages/codegen-ui-react/lib/imports/import-collection.ts b/packages/codegen-ui-react/lib/imports/import-collection.ts
index 2d357a009..803f2e6d1 100644
--- a/packages/codegen-ui-react/lib/imports/import-collection.ts
+++ b/packages/codegen-ui-react/lib/imports/import-collection.ts
@@ -23,6 +23,10 @@ import { createUniqueName } from '../helpers';
export class ImportCollection {
constructor(componentMetadata?: ComponentMetadata) {
this.importedNames = new Set(Object.values(componentMetadata?.componentNameToTypeMap || {}).concat(reservedWords));
+ // Add form fields so we dont reuse the identifier
+ if (componentMetadata?.formMetadata) {
+ Object.keys(componentMetadata.formMetadata.fieldConfigs).forEach((key) => this.importedNames.add(key));
+ }
}
importedNames: Set;
diff --git a/packages/codegen-ui/example-schemas/datastore/project-team-model.json b/packages/codegen-ui/example-schemas/datastore/project-team-model.json
index 8e7ef77af..e30ccc75c 100644
--- a/packages/codegen-ui/example-schemas/datastore/project-team-model.json
+++ b/packages/codegen-ui/example-schemas/datastore/project-team-model.json
@@ -6,8 +6,8 @@
"id": { "name": "id", "isArray": false, "type": "ID", "isRequired": true, "attributes": [] },
"name": { "name": "name", "isArray": false, "type": "String", "isRequired": false, "attributes": [] },
"teamID": { "name": "teamID", "isArray": false, "type": "ID", "isRequired": true, "attributes": [] },
- "team": {
- "name": "team",
+ "Team": {
+ "name": "Team",
"isArray": false,
"type": { "model": "Team" },
"isRequired": false,
@@ -103,8 +103,8 @@
"fields": {
"id": { "name": "id", "isArray": false, "type": "ID", "isRequired": true, "attributes": [] },
"name": { "name": "name", "isArray": false, "type": "String", "isRequired": true, "attributes": [] },
- "team": {
- "name": "team",
+ "Team": {
+ "name": "Team",
"isArray": false,
"type": { "model": "Team" },
"isRequired": false,
diff --git a/packages/codegen-ui/example-schemas/forms/member-datastore-create.json b/packages/codegen-ui/example-schemas/forms/member-datastore-create.json
index 932419339..11856dea2 100644
--- a/packages/codegen-ui/example-schemas/forms/member-datastore-create.json
+++ b/packages/codegen-ui/example-schemas/forms/member-datastore-create.json
@@ -6,7 +6,7 @@
"dataTypeName": "Member"
},
"fields": {
- "team": {
+ "Team": {
"inputType": {
"type": "Autocomplete",
"valueMappings": {