---
order: 8
zh-CN:
	title: FieldArray 基本使用
	addHobby: 添加兴趣爱好
	delHobby: 删除该爱好
	hobby: 兴趣爱好
	hobbyValidation: 请填写兴趣爱好
	hobbyLimit: 最多添加 3 项兴趣
	addMember: 添加一个成员
	addTwoMembers: 添加两个成员
	delMember: 删除该成员
	member: 成员
	name: 名字
	sex: 性别
	nameValidationError: 请填写成员名字
	sexValidationError: 请选择性别
	male: 男
	female: 女
	totalNumber: 总人数
	totalNumberError: 请填写总人数
	submit: 获取表单值
	submitValue: 获取表单提交值
	setArray: 设置 FieldArray 值
en-US:
	title: Basic usage of FieldArray
	addHobby: Add hobby
	delHobby: Delete hobby
	hobby: Hobby
	hobbyValidation: Please enter the hobby
	hobbyLimit: Too many hobbies, at most 3
	addMember: Add one member
	addTwoMembers: Add two members
	delMember: Delete member
	member: Member
	name: Name
	sex: Sex
	nameValidationError: Please enter the name of member.
	sexValidationError: Please select the sex of member.
	male: male
	female: female
	totalNumber: Total number
	totalNumberError: Please enter the total number of the family.
	submit: Get Form Value
	submitValue: Get Submit Value
	setArray: Set FieldArray
---

```jsx
import {
	Form,
	FormError,
	Icon,
	Pop,
	Notify,
	FieldModel,
	FieldSetModel,
	FieldSet,
	Validators,
	ValidatorOption,
	FormStrategy,
	FormNumberInputField,
} from 'zent';

function Hobbies({ name }) {
	const model = Form.useFieldArray(name, [
		Validators.maxLength(3, '{i18n.hobbyLimit}'),
	]);
	const addHobby = useCallback(() => {
		model.push('');
		model.validate(ValidateOption.IncludeUntouched);
	}, []);
	return (
		<>
			<Button onClick={addHobby} className="add-btn">
				{i18n.addHobby}
			</Button>
			<ul>
				{model.children.map((child, index) => (
					<li key={child.id} className="hobby">
						<FormInputField
							model={child}
							label={`{i18n.hobby}${index + 1}：`}
							validators={[Validators.required('{i18n.hobbyValidation}')]}
							props={{
								width: 120,
							}}
						/>
						<span
							className="del-btn"
							onClick={() => {
								model.splice(index, 1);
								model.validate();
							}}
						>
							{i18n.delHobby}
						</span>
					</li>
				))}
			</ul>
			<FormError style={{ marginLeft: 128 }}>{model.error?.message}</FormError>
		</>
	);
}

function MemberInfo({ remove, index }) {
	const onRemoveClick = useCallback(() => {
		remove(index);
	}, [index, remove]);
	return (
		<li className="members">
			<div className="member-title">
				<span>
					{i18n.member}
					{index + 1}
				</span>
				<Pop centerArrow trigger="hover" content="{i18n.delMember}">
					<Icon
						className="del-btn"
						type="close-circle"
						onClick={onRemoveClick}
					/>
				</Pop>
			</div>
			<FormInputField
				name="name"
				label="{i18n.name}:"
				required
				validators={[Validators.required('{i18n.nameValidationError}')]}
				normalizeBeforeSubmit={name => name.toUpperCase()}
			/>
			<FormRadioGroupField
				name="sex"
				label="{i18n.sex}："
				defaultValue="1"
				required
				validators={[Validators.required('{i18n.sexValidationError}')]}
			>
				<Radio value="1">{i18n.male}</Radio>
				<Radio value="2">{i18n.female}</Radio>
			</FormRadioGroupField>
			<Hobbies name="hobbies" />
		</li>
	);
}

function Members({ name }) {
	const model = Form.useFieldArray(name);
	const addOne = useCallback(() => {
		model.push({});
	}, [model]);
	const addTwo = useCallback(() => {
		model.push({}, {});
	}, [model]);
	const remove = useCallback(
		index => {
			model.splice(index, 1);
		},
		[model]
	);
	return (
		<>
			{model.children.length < 3 && (
				<Button onClick={addOne} className="add-btn">
					{i18n.addMember}
				</Button>
			)}
			{model.children.length < 2 && (
				<Button onClick={addTwo} className="add-btn">
					{i18n.addTwoMembers}
				</Button>
			)}
			<ul>
				{model.children.map((child, index) => (
					<FieldSet key={child.id} model={child}>
						<MemberInfo index={index} remove={remove} />
					</FieldSet>
				))}
			</ul>
		</>
	);
}

function App() {
	const form = Form.useForm(FormStrategy.View);
	const setArray = useCallback(() => {
		form.patchValue({
			number: 42,
			members: [
				{
					name: 'john',
					sex: '1',
					hobbies: ['H1'],
				},
			],
		});
	}, [form]);

	const getFormValue = useCallback(() => {
		console.log(form.getValue());
	}, [form]);

	const getSubmitValue = useCallback(() => {
		console.log(form.getSubmitValue());
	}, [form]);

	return (
		<Form className="demo-form" layout="horizontal" form={form}>
			<FormNumberInputField
				name="number"
				label="{i18n.totalNumber}："
				required
				validators={[Validators.required('{i18n.totalNumberError}')]}
			/>
			<Members name="members" />
			<div style={{ marginTop: 16 }}>
				<Button type="primary" htmlType="submit" onClick={getFormValue}>
					{i18n.submit}
				</Button>
				<Button type="primary" htmlType="submit" onClick={getSubmitValue}>
					{i18n.submitValue}
				</Button>
				<Button onClick={setArray}>{i18n.setArray}</Button>
			</div>
		</Form>
	);
}

ReactDOM.render(<App />, mountNode);
```

<style>
.add-btn {
	margin-left: 130px;
}

.demo-form {

	.members {
		border: 1px dashed #ccc;
		margin: 20px 0;
		padding: 10px 0;
		position: relative;

		.del-btn {
			color: #666;
			cursor: pointer;
			position: absolute;
			right: -8px;
			top: -8px;
		}
	}

	.member-title{
		margin: 0 10px;
	}

	.hobby {
		margin-top: 20px;
		position: relative;

		.del-btn {
			color: #155bd4;
			cursor: pointer;
			font-size: 12px;
			position: absolute;
			top: 6px;
			left: 300px;
			width: 100px;
		}
	}

	.hobby-title {
		margin: 10px 0 5px;
	}

	.zenticon {
		margin-left: 10px;
	}
}
</style>
