zent
Version:
一套前端设计语言和基于React的实现
232 lines (219 loc) • 5.21 kB
Markdown
---
order: 9
zh-CN:
title: 从 Model 构建表单
addHobby: 添加兴趣爱好
delHobby: 删除该爱好
hobby: 兴趣爱好
hobbyValidation: 请填写兴趣爱好
addMember: 添加一个成员
addTwoMembers: 添加两个成员
delMember: 删除该成员
member: 成员
name: 名字
sex: 性别
nameValidationError: 请填写成员名字
sexValidationError: 请选择性别
male: 男
female: 女
totalNumber: 总人数
totalNumberError: 请填写总人数
submit: 获取表单值
submitValue: 获取表单提交值
setArray: 设置 FieldArray 值
en-US:
title: build form from model
addHobby: Add hobby
delHobby: Delete hobby
hobby: Hobby
hobbyValidation: Please enter the hobby.
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,
Icon,
Pop,
Notify,
FieldModel,
FieldSetModel,
FieldSet,
Validators,
FormStrategy,
FormNumberInputField,
} from 'zent';
const { form, field, array, set } = Form;
function hobbyFactory(defaultValue = '') {
return field(defaultValue);
}
function Hobbies({ model: propsModel }) {
const model = Form.useFieldArray(propsModel);
const addHobby = useCallback(() => {
model.push('');
}, []);
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}:`}
props={{
width: 120,
}}
/>
<span className="del-btn" onClick={() => model.splice(index, 1)}>
{i18n.delHobby}
</span>
</li>
))}
</ul>
</>
);
}
function MemberInfo({ remove, index, model }) {
const { name, sex, hobbies } = model.children;
const onRemoveClick = useCallback(() => {
remove(index);
}, [index, remove]);
return (
<FieldSet model={model}>
<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
model={name}
label="{i18n.name}:"
required
/>
<FormRadioGroupField model={sex} label="{i18n.sex}:" required>
<Radio value="1">{i18n.male}</Radio>
<Radio value="2">{i18n.female}</Radio>
</FormRadioGroupField>
<Hobbies model={hobbies} />
</li>
</FieldSet>
);
}
function Members({ model: propsModel }) {
const model = Form.useFieldArray(propsModel);
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) => (
<MemberInfo key={child.id} model={child} index={index} remove={remove} />
))}
</ul>
</>
);
}
const formBuilder = form({
number: field('').validators(Validators.required('{i18n.totalNumberError}')),
members: array(
set({
name: field('')
.validators(Validators.required('{i18n.nameValidationError}'))
.normalizeBeforeSubmit(name => name.toUpperCase()),
sex: field('1').validators(
Validators.required('{i18n.sexValidationError}')
),
hobbies: array(
field('').validators(Validators.required('{i18n.hobbyValidation}'))
).defaultValue([]),
})
),
});
function App() {
const form = Form.useForm(formBuilder);
const { number, members } = form.model.children;
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
model={number}
label="{i18n.totalNumber}:"
required
/>
<Members model={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);
```