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.
Source
@saas-ui/forms
- 2.8.9 (latest)
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
Auto generated form
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 (<FormdefaultValues={{title: '',todos: [],}}schema={schema}onSubmit={() => null}/>)}
Basic object array
Field names inside an ArrayField
need to be prefixed with array-field-name.$
. The $
will be replaced with the index of the array item.
import { SubmitButton } from '@saas-ui/react'import { Form } from '@saas-ui/forms/yup'import * as yup from 'yup'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),}))export default function CreateIssue() {return (<Formschema={schema}defaultValues={{title: '',issues: [{ title: '' }],}}onSubmit={() => Promise.resolve()}>{({ Field, ArrayField }) => (<FormLayout><Field name="title" label="Title" /><ArrayField name="issues" label="Sub-issues"><Field name="issues.$.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.
import { SubmitButton } from '@saas-ui/react'import { Form } from '@saas-ui/forms/yup'import * as yup from 'yup'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),})export default function CustomArrayField() {return (<Formschema={schema}defaultValues={{users: [{id: '123',name: 'Eelco',lastName: 'Wiersma',},],}}onSubmit={() => Promise.resolve()}>{({ Field }) => (<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="users.$.id" placeholder="Id" /><Field name="users.$.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.
import { Button } from '@saas-ui/react'import {useArrayFieldContext,useArrayFieldAddButton,useArrayFieldRemoveButton,} from '@saas-ui/react'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
import { Button } from '@chakra-ui/react'import { SubmitButton } from '@saas-ui/react'import { Form } from '@saas-ui/forms/yup'import * as yup from 'yup'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),}))export default function CreateIssue() {const ref = React.useRef(null)return (<FormdefaultValues={{title: '',issues: [{ title: '' }],}}onSubmit={() => Promise.resolve()}>{({ Field, ArrayField }) => (<FormLayout><Field name="title" label="Title" /><ArrayField name="issues" label="Sub-issues" ref={ref}><Field name="issues.$.title" placeholder="Sub-issue title" /></ArrayField><ButtononClick={() =>ref.current.append({ title: 'Appended using the ref api' })}>Add todo</Button><SubmitButton>Create todo</SubmitButton></FormLayout>)}</Form>)}
Was this helpful?