Name:
interface
Value:
Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated Jul 30, 2024

Customize form inputs

In this guide, you will learn how to customize connected forms that are generated by running npx ampx generate forms. Before you begin you will need:

  • Your cloud sandbox with an Amplify Data resource up and running (npx ampx sandbox)
  • A frontend application that has generated a connected form

All Amplify forms are built with the Amplify UI library. The generated form provides a mechanism to override properties for each individual input component, like TextField, TextAreaField, SelectField. You can override any props to those components with the overrides prop on the form component. For example, if you want to change the variation and label of the content field in the TodoCreateForm:

import TodoCreateForm from '@/ui-components/TodoCreateForm'
<TodoCreateForm
overrides={{
content: {
variation: 'quiet',
label: 'Todo'
}
}}
/>

Note: We do not recommend overriding properties that are already set by the generated form. This could lead to unexpected behavior during runtime. Verify the set properties by navigating to the component in the src/ui-components/[your-form-component].jsx file.

You own updating the code directly for the generated form. Here's how you can customize the form.

Manually add form input field

You can manually add a form input connected to a data model to the generated form. For example, let's say you add a priority field to your data model. Make the following edits to the generated form:

src/ui-components/TodoCreateForm.js
// 1. Set initialValues
const initialValues = {
content: "",
priority: "" // Initial value for priority
};
// 2. State setup
const [priority, setPriority] = React.useState(initialValues.priority);
// 3. Update resetValues
const resetStateValues = () => {
.. // previous fields
setPriority(initialValues.priority)
setErrors({});
};
// 4. Validation setup
const validations = {
content: [],
priority: [] // Assuming no special validations for now
};
// 5. Update form submission
onSubmit={async (event) => {
event.preventDefault();
let modelFields = {
..,
priority
};
// 6. Add TextField
<TextField
label="Priority"
isRequired={false}
isReadOnly={false}
value={priority}
onChange={(e) => {
let { value } = e.target;
if (onChange) {
const modelFields = {
priority: value,
};
const result = onChange(modelFields);
value = result?.priority ?? value;
}
if (errors.priority?.hasError) {
runValidationTasks("priority", value);
}
setPriority(value);
}}
onBlur={() => runValidationTasks("priority", priority)}
errorMessage={errors.priority?.errorMessage}
hasError={errors.priority?.hasError}
{...getOverrideProps(overrides, "priority")}
/>

Manually add option fields

Select Fields, Radio Group Fields, and Autocomplete Fields require a set of options for your users to choose from. For example, a "Status" input can only have the options "Not started", "In progress", and "Done". This would be identical to the above 6 steps, but in step 6 you would replace <TextField> with <SelectField>

src/ui-components/TodoCreateForm.js
// 6. Import <SelectField> component and add to form return
<SelectField
label="Label"
placeholder="Please select an option"
value={status}
onChange={(e) => {
let { value } = e.target;
if (onChange) {
const modelFields = {
status: value
};
const result = onChange(modelFields);
value = result?.status ?? value;
}
if (errors.status?.hasError) {
runValidationTasks("status", value);
}
setStatus(value);
}}
onBlur={() => runValidationTasks("status", status)}
errorMessage={errors.status?.errorMessage}
hasError={errors.status?.hasError}
{...getOverrideProps(overrides, "status")}
>
<option children="Not started" value="Not started" {...getOverrideProps(overrides, "statusOption0")}></option>
<option children="In progress" value="In progress" {...getOverrideProps(overrides, "statusOption1")}></option>
<option children="Done" value="Done" {...getOverrideProps(overrides, "statusOption2")}></option>
</SelectField>

Configure form spacings (paddings and gaps)

Add spacing to your form and between inputs. Spacing values can either be a CSS length value (px, rem, em, %) or a reference to your theme object's spacing value (xss, medium, large).

import TodoCreateForm from '@/ui-components/TodoCreateForm'
<TodoCreateForm overrides={{
TodoCreateForm: {
rowGap: 'xl', // horizontal gap between inputs
columnGap: 'xs', // vertical gap between inputs
padding: 'xl', // padding around form
},
}} />

Customize label for Submit and Clear buttons

You can customize action button labels to better describe your form's use case, such as changing Submit to Create Todo.

import TodoCreateForm from '@/ui-components/TodoCreateForm'
<TodoCreateForm overrides={{
ClearButton: {
children: 'Close'
},
SubmitButton: {
children: 'Save todo'
}
}} />

Toggle visibility for Submit and Clear buttons

You can customize the visibility of action buttons to better accommodate your form's use case.

import TodoCreateForm from '@/ui-components/TodoCreateForm'
<TodoCreateForm overrides={{
ClearButton: {
display: 'none'
},
SubmitButton: {
display: 'none'
}
}} />

If you hide all form action buttons, you can still leverage the onChange event handler to self-manage the form lifecycle. This is useful for a form that updates data in real-time without explicit user confirmation.

import TodoCreateForm from '@/ui-components/TodoCreateForm'
<TodoCreateForm
onChange={(fields) => {
console.log({ fields })
// make sure you return fields!
return fields
}}
/>