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 397aad288..59e62c4fa 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 @@ -2157,6 +2157,7 @@ import { Heading, Icon, ScrollView, + SwitchField, Text, TextField, useTheme, @@ -2303,6 +2304,7 @@ export default function NestedJson(props) { Nicknames1: [], \\"nick-names2\\": [], \\"first Name\\": undefined, + options: {}, }; const [firstName, setFirstName] = React.useState(initialValues[\\"first-Name\\"]); const [lastName, setLastName] = React.useState(initialValues.lastName); @@ -2314,6 +2316,7 @@ export default function NestedJson(props) { const [firstName1, setFirstName1] = React.useState( initialValues[\\"first Name\\"] ); + const [options, setOptions] = React.useState(initialValues.options); const [errors, setErrors] = React.useState({}); const resetStateValues = () => { setFirstName(initialValues[\\"first-Name\\"]); @@ -2324,6 +2327,7 @@ export default function NestedJson(props) { setNicknames(initialValues[\\"nick-names2\\"]); setCurrentNicknamesValue(undefined); setFirstName1(initialValues[\\"first Name\\"]); + setOptions(initialValues.options); setErrors({}); }; const [currentBioFavoritetreesValue, setCurrentBioFavoritetreesValue] = @@ -2344,6 +2348,7 @@ export default function NestedJson(props) { Nicknames1: [], \\"nick-names2\\": [], \\"first Name\\": [], + \\"options.enabled\\": [], }; const runValidationTasks = async (fieldName, value) => { let validationResponse = validateField(value, validations[fieldName]); @@ -2369,6 +2374,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const validationResponses = await Promise.all( Object.keys(validations).reduce((promises, fieldName) => { @@ -2406,6 +2412,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); value = result?.[\\"first-Name\\"] ?? value; @@ -2432,6 +2439,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); value = result?.lastName ?? value; @@ -2463,6 +2471,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); value = result?.bio?.[\\"favorite Quote\\"] ?? value; @@ -2491,6 +2500,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); value = result?.bio?.[\\"favorite-Animal\\"] ?? value; @@ -2518,6 +2528,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); values = result?.bio?.[\\"favorite-trees\\"] ?? values; @@ -2555,6 +2566,11 @@ export default function NestedJson(props) { {...getOverrideProps(overrides, \\"bio.favorite-trees\\")} > + { let values = items; @@ -2566,6 +2582,7 @@ export default function NestedJson(props) { Nicknames1: values, \\"nick-names2\\": nicknames, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); values = result?.Nicknames1 ?? values; @@ -2611,6 +2628,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": values, \\"first Name\\": firstName1, + options, }; const result = onChange(modelFields); values = result?.[\\"nick-names2\\"] ?? values; @@ -2657,6 +2675,7 @@ export default function NestedJson(props) { Nicknames1, \\"nick-names2\\": nicknames, \\"first Name\\": value, + options, }; const result = onChange(modelFields); value = result?.[\\"first Name\\"] ?? value; @@ -2671,6 +2690,35 @@ export default function NestedJson(props) { hasError={errors[\\"first Name\\"]?.hasError} {...getOverrideProps(overrides, \\"first Name\\")} > + { + let value = e.target.checked; + if (onChange) { + const modelFields = { + \\"first-Name\\": firstName, + lastName, + bio, + Nicknames1, + \\"nick-names2\\": nicknames, + \\"first Name\\": firstName1, + options: { ...options, enabled: value }, + }; + const result = onChange(modelFields); + value = result?.options?.enabled ?? value; + } + if (errors[\\"options.enabled\\"]?.hasError) { + runValidationTasks(\\"options.enabled\\", value); + } + setOptions({ ...options, enabled: value }); + }} + onBlur={() => runValidationTasks(\\"options.enabled\\", options[\\"enabled\\"])} + errorMessage={errors[\\"options.enabled\\"]?.errorMessage} + hasError={errors[\\"options.enabled\\"]?.hasError} + {...getOverrideProps(overrides, \\"options.enabled\\")} + > ; @@ -2740,6 +2791,9 @@ export declare type NestedJsonValidationValues = { \\"favorite-Animal\\"?: ValidationFunction; \\"favorite-trees\\"?: ValidationFunction; }; + options?: { + enabled?: ValidationFunction; + }; }; export declare type FormProps = Partial & React.DOMAttributes; export declare type NestedJsonOverridesProps = { @@ -2750,9 +2804,11 @@ export declare type NestedJsonOverridesProps = { \\"bio.favorite Quote\\"?: FormProps; \\"bio.favorite-Animal\\"?: FormProps; \\"bio.favorite-trees\\"?: FormProps; + options?: FormProps; Nicknames1?: FormProps; \\"nick-names2\\"?: FormProps; \\"first Name\\"?: FormProps; + \\"options.enabled\\"?: FormProps; } & EscapeHatchProps; export declare type NestedJsonProps = React.PropsWithChildren<{ overrides?: NestedJsonOverridesProps | undefined | null; diff --git a/packages/codegen-ui-react/lib/forms/component-helper.ts b/packages/codegen-ui-react/lib/forms/component-helper.ts index 839ed1ee0..2103158ff 100644 --- a/packages/codegen-ui-react/lib/forms/component-helper.ts +++ b/packages/codegen-ui-react/lib/forms/component-helper.ts @@ -17,6 +17,7 @@ import { FieldConfigMetadata, StudioDataSourceType, StudioFormActionType } from '@aws-amplify/codegen-ui'; import { BinaryExpression, factory, Identifier, JsxAttribute, SyntaxKind } from 'typescript'; import { resetValuesName } from './form-state'; +import { FIELD_TYPE_TO_TYPESCRIPT_MAP } from './typescript-type-map'; export const ControlledComponents = ['StepperField', 'SliderField', 'SelectField', 'ToggleButton', 'SwitchField']; @@ -76,7 +77,7 @@ export const renderValueAttribute = ({ const componentType = fieldConfig.studioFormComponentType ?? fieldConfig.componentType; const shouldGetForUncontrolled = fieldConfig.isArray; - const valueIdentifier = currentValueIdentifier || factory.createIdentifier(componentName.split('.')[0]); + const valueIdentifier = currentValueIdentifier || getValueIdentifier(componentName, componentType); const controlledComponentToAttributesMap: { [key: string]: JsxAttribute } = { ToggleButton: factory.createJsxAttribute( @@ -152,3 +153,12 @@ export const resetFunctionCheck = ({ } return []; }; + +const getValueIdentifier = (componentName: string, componentType: string) => { + // For Boolean components like SwitchField, they need the full dot notation name + // e.g. isChecked={options.enabled} + if (FIELD_TYPE_TO_TYPESCRIPT_MAP[componentType] === SyntaxKind.BooleanKeyword) { + return factory.createIdentifier(componentName); + } + return factory.createIdentifier(componentName.split('.')[0]); +}; diff --git a/packages/codegen-ui/example-schemas/forms/bio-nested-create.json b/packages/codegen-ui/example-schemas/forms/bio-nested-create.json index c51488685..176249b4f 100644 --- a/packages/codegen-ui/example-schemas/forms/bio-nested-create.json +++ b/packages/codegen-ui/example-schemas/forms/bio-nested-create.json @@ -79,6 +79,12 @@ "position": { "below": "bio.favorite-Animal" } + }, + "options.enabled" : { + "inputType" : { + "type" : "SwitchField" + }, + "label" : "Enabled" } }, "formActionType": "create", @@ -91,6 +97,14 @@ }, "text": "bio", "type": "Heading" + }, + "options" : { + "level" : 3, + "position" : { + "below" : "bio.favorite-trees" + }, + "text" : "Options", + "type" : "Heading" } }, "style": {