The field name
ArrayField
Form field component to handle array type values.
The ArrayField
helps you to create complex forms with ease.
It uses React Hook Forms useFieldArray
internally.
Import#
ArrayField
: The wrapper component that composes the default ArrayField functionality.ArrayFieldContainer
: The container component provides context and state management.ArrayFieldRows
: Render prop component, to get access to the internal fields state. Must be a child ofArrayFieldContainer
.ArrayFieldRowContainer
: The row container component providers row context.ArrayFieldRowFields
: Add the name prefix to the fields and acts as a horizontal form layout by default.ArrayFieldAddButton
: The default add button.ArrayFieldRemoveButton
: The default remove button.useArrayFieldContext
: A hook that returns theArrayField
internal state.useArrayFieldRowContext
: A hook that returns theArrayFieldRowContainer
state.useArrayFieldAddButton
: A hook that can be used to create a custom add button.useArrayFieldRemoveButton
: A hook that can be used to create a custom remove button.
import {ArrayField,ArrayFieldContainer,ArrayFieldRows,ArrayFieldRowContainer,ArrayFieldRowFields,ArrayFieldAddButton,ArrayFieldRemoveButton,useArrayFieldContext,useArrayFieldRowContext,useArrayFieldAddButton,useArrayFieldRemoveButton,} from '@saas-ui/react'
Usage#
Usage with AutoForm
#
Simple array of string values.
function CreateTodoItem() {const schema = {title: {label: 'Title',rules: {required: true,},},todos: {type: 'array',min: 1,items: {type: 'object',properties: {todo: {label: 'Todo',},},},},}return (<AutoFormdefaultValues={{title: '',todos: [],}}schema={schema}onSubmit={() => null}/>)}
Usage with Form
#
Basic object array. The ArrayField
component will automatically prefix all sub fields.
Eg: issues.0.title
, issues.1.title
etc.
Please note that this only works if the fields are a direct child. Read further to see how to create more complex array fields.
function CreateIssue() {const issueSchema = Yup.object().shape({title: Yup.string().required().label('Title'),})const schema = issueSchema.concat(Yup.object().shape({issues: Yup.array().min(1).max(4).of(issueSchema),}))return (<FormdefaultValues={{title: '',issues: [{ title: '' }],}}resolver={yupResolver(schema)}onSubmit={() => null}><FormLayout><Field name="title" label="Title" /><ArrayField name="issues" label="Sub-issues"><Field name="title" placeholder="Sub-issue title" /></ArrayField><SubmitButton>Create todo</SubmitButton></FormLayout></Form>)}
Complex array field#
The array field can be fully composed to fit your specific use case.
function CustomArrayField() {const usersSchema = Yup.object().shape({id: Yup.string().required().label('Id'),name: Yup.string().required().label('Name'),lastName: Yup.string().required().label('Last name'),})const schema = Yup.object().shape({users: Yup.array().min(1).max(4).of(usersSchema),})return (<FormdefaultValues={{users: [{id: '123',name: 'Eelco',lastName: 'Wiersma',},],}}resolver={yupResolver(schema)}onSubmit={() => Promise.resolve()}><FormLayout><ArrayFieldContainername="users"label="Users"defaultValue={{}}keyName="key"min={2}max={4}><ArrayFieldRows>{(fields) => (<>{fields.map((field, i) => {return (<ArrayFieldRowContainer key={field.key} index={i}><ArrayFieldRowFields columns={3} spacing={1}><Field name="id" placeholder="Id" /><Field name="name" placeholder="Name" /><Box><Fieldname={`users.${i}.lastName`}placeholder="Last name"/></Box></ArrayFieldRowFields><ArrayFieldRemoveButton /></ArrayFieldRowContainer>)})}</>)}</ArrayFieldRows><ArrayFieldAddButton /></ArrayFieldContainer><SubmitButton label="Submit" /></FormLayout></Form>)}
Custom buttons#
Use the useArrayFieldContext
and useArrayFieldRowContext
hooks to interact with the ArrayFieldContainer and create advanced custom components.
The useArrayFieldAddButton
and useArrayFieldRemoveButton
hooks can be used to create custom buttons.
const SimpleAddButton = () => {return <Button {...useArrayFieldAddButton()}>Add record</Button>}const CustomAddButton = () => {const { append, defaultValue, max, fields } = useArrayFieldContext()const isDisabled = !!(max && fields.length >= max)return (<ButtononClick={() =>append(defaultValue, {shouldFocus: true,focusName: `arrayField.${fields.length}.id`,})}isDisabled={isDisabled}>Add record</Button>)}const RemoveButton = () => {return (<Button variant="ghost" {...useArrayFieldRemoveButton()}>Remove</Button>)}
Accessing the ArrayField context#
You can access the ArrayField context by using a ref, or using useArrayFieldContext
function CreateIssue() {const ref = React.useRef(null)React.useLayoutEffect(() => {console.log(ref.current)ref.current.append({ title: 'Appended using the ref api' })}, [ref])const issueSchema = Yup.object().shape({title: Yup.string().required().label('Title'),})const schema = issueSchema.concat(Yup.object().shape({issues: Yup.array().min(1).max(4).of(issueSchema),}))return (<FormdefaultValues={{title: '',issues: [{ title: '' }],}}resolver={yupResolver(schema)}onSubmit={() => null}><FormLayout><Field name="title" label="Title" /><ArrayField name="issues" label="Sub-issues" ref={ref}><Field name="title" placeholder="Sub-issue title" /></ArrayField><SubmitButton>Create todo</SubmitButton></FormLayout></Form>)}
Props#
ArrayField Props#
name
required
name
required
string
defaultValue
defaultValue
Default value for new values in the array
Record<string, any>
help
help
Field help text
string
hideLabel
hideLabel
Hide the field label
boolean
keyName
keyName
Default key name for rows, change this if your data uses a different 'id' field
string
"id"
label
label
The field label
string
max
max
number
min
min
number
placeholder
placeholder
The input placeholder
string
ref
ref
ForwardedRef<UseArrayFieldReturn>
rules
rules
React hook form rules
Omit<Partial<{ required: string | ValidationRule<boolean>; min: ValidationRule<string | number>; max: ValidationRule<string | number>; ... 12 more ...; deps: string | string[]; }>, "disabled" | ... 2 more ... | "setValueAs">
type
type
Build-in types: - text - number - password - textarea - select - native-select - checkbox - radio - switch - pin Will default to a text field if there is no matching type.
string
Was this helpful?