Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: nested boolean field isn't controlled #783

Merged
merged 1 commit into from
Nov 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2157,6 +2157,7 @@ import {
Heading,
Icon,
ScrollView,
SwitchField,
Text,
TextField,
useTheme,
Expand Down Expand Up @@ -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);
Expand All @@ -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\\"]);
Expand All @@ -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] =
Expand All @@ -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]);
Expand All @@ -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) => {
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -2555,6 +2566,11 @@ export default function NestedJson(props) {
{...getOverrideProps(overrides, \\"bio.favorite-trees\\")}
></TextField>
</ArrayField>
<Heading
level={3}
children=\\"Options\\"
{...getOverrideProps(overrides, \\"options\\")}
></Heading>
<ArrayField
onChange={async (items) => {
let values = items;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -2671,6 +2690,35 @@ export default function NestedJson(props) {
hasError={errors[\\"first Name\\"]?.hasError}
{...getOverrideProps(overrides, \\"first Name\\")}
></TextField>
<SwitchField
label=\\"Enabled\\"
defaultChecked={false}
isChecked={options.enabled}
awinberg-aws marked this conversation as resolved.
Show resolved Hide resolved
onChange={(e) => {
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\\")}
></SwitchField>
<Flex
justifyContent=\\"space-between\\"
{...getOverrideProps(overrides, \\"CTAFlex\\")}
Expand Down Expand Up @@ -2711,7 +2759,7 @@ export default function NestedJson(props) {
exports[`amplify form renderer tests custom form tests should render nested json fields 2`] = `
"import * as React from \\"react\\";
import { EscapeHatchProps } from \\"@aws-amplify/ui-react/internal\\";
import { GridProps, HeadingProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
import { GridProps, HeadingProps, SwitchFieldProps, TextFieldProps } from \\"@aws-amplify/ui-react\\";
export declare type ValidationResponse = {
hasError: boolean;
errorMessage?: string;
Expand All @@ -2728,6 +2776,9 @@ export declare type NestedJsonInputValues = {
\\"favorite-Animal\\"?: string;
\\"favorite-trees\\"?: string[];
};
options?: {
enabled?: boolean;
};
};
export declare type NestedJsonValidationValues = {
\\"first-Name\\"?: ValidationFunction<string>;
Expand All @@ -2740,6 +2791,9 @@ export declare type NestedJsonValidationValues = {
\\"favorite-Animal\\"?: ValidationFunction<string>;
\\"favorite-trees\\"?: ValidationFunction<string>;
};
options?: {
enabled?: ValidationFunction<boolean>;
};
};
export declare type FormProps<T> = Partial<T> & React.DOMAttributes<HTMLDivElement>;
export declare type NestedJsonOverridesProps = {
Expand All @@ -2750,9 +2804,11 @@ export declare type NestedJsonOverridesProps = {
\\"bio.favorite Quote\\"?: FormProps<TextFieldProps>;
\\"bio.favorite-Animal\\"?: FormProps<TextFieldProps>;
\\"bio.favorite-trees\\"?: FormProps<TextFieldProps>;
options?: FormProps<HeadingProps>;
Nicknames1?: FormProps<TextFieldProps>;
\\"nick-names2\\"?: FormProps<TextFieldProps>;
\\"first Name\\"?: FormProps<TextFieldProps>;
\\"options.enabled\\"?: FormProps<SwitchFieldProps>;
} & EscapeHatchProps;
export declare type NestedJsonProps = React.PropsWithChildren<{
overrides?: NestedJsonOverridesProps | undefined | null;
Expand Down
12 changes: 11 additions & 1 deletion packages/codegen-ui-react/lib/forms/component-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'];

Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,12 @@
"position": {
"below": "bio.favorite-Animal"
}
},
"options.enabled" : {
"inputType" : {
"type" : "SwitchField"
},
"label" : "Enabled"
}
},
"formActionType": "create",
Expand All @@ -91,6 +97,14 @@
},
"text": "bio",
"type": "Heading"
},
"options" : {
"level" : 3,
"position" : {
"below" : "bio.favorite-trees"
},
"text" : "Options",
"type" : "Heading"
}
},
"style": {
Expand Down