zent
Version:
一套前端设计语言和基于React的实现
139 lines (122 loc) • 3.62 kB
Markdown
---
order: 22
zh-CN:
title: Model 模式动态增删表单项
invalidContactType: 请选择联系方式
invalidPhoneNumber: 手机号必须是 11 位数字
invalidEmail: 邮箱不正确
labelContactType: 联系方式
labelPhone: 手机号码
labelEmail: 电子邮箱
preserveState: 切换联系方式时时保留 model 状态
printValue: 打印表单值
en-US:
title: Add/remove fields in Model mode
invalidContactType: Contact type is required
invalidPhoneNumber: Phone number is 11 digits
invalidEmail: Invalid email address
labelContactType: Contact type
labelPhone: Phone
labelEmail: Email
preserveState: Preserve model state while switching contact type
printValue: Print form value
---
```jsx
import {
Form,
Validators,
FormRadioGroupField,
FormNumberInputField,
FormInputField,
Checkbox,
} from 'zent';
import { merge } from 'rxjs';
const { form, field } = Form;
const ContactType = {
Phone: 1,
Email: 2,
};
const formBuilder = form({
contactType: field(ContactType.Phone).validators(
Validators.required('{i18n.invalidContactType}')
),
phone: field('').validators(
Validators.pattern(/\d{11}/, '{i18n.invalidPhoneNumber}')
),
email: field('').validators(Validators.email('{i18n.invalidEmail}')),
});
function App() {
const [preserveState, setPreserveState] = React.useState(false);
const onPreserveStateChange = React.useCallback(
evt => {
setPreserveState(evt.target.checked);
},
[ ]
);
const form = Form.useForm(formBuilder);
const removedModelRef = React.useRef(null);
const swapModel = React.useCallback(
(oldName, newName) => {
const prevModel = removedModelRef.current;
const oldModel = form.model.removeChild(oldName);
if (oldModel !== null) {
removedModelRef.current = oldModel;
}
if (!form.model.get(newName)) {
const newModel = preserveState ? prevModel : prevModel.builder.build();
form.model.registerChild(newName, newModel);
}
},
[ ]
);
const contactTypeValue = Form.useModelValue(form.model.get('contactType'));
React.useEffect(() => {
if (contactTypeValue === ContactType.Phone) {
swapModel('email', 'phone');
} else {
swapModel('phone', 'email');
}
}, [swapModel, contactTypeValue]);
const getFormValue = React.useCallback(() => {
console.log(form.getValue(), form.isValid());
}, [form]);
// `useNamedChildModel` will trigger a render whenever a model is removed or registered
const phoneModel = Form.useNamedChildModel(form.model, 'phone');
const emailModel = Form.useNamedChildModel(form.model, 'email');
return (
<Form className="demo-form" layout="horizontal" form={form}>
<FormRadioGroupField
model={form.model.get('contactType')}
label="{i18n.labelContactType}"
required
>
<Radio value={ContactType.Phone}>{i18n.labelPhone}</Radio>
<Radio value={ContactType.Email}>{i18n.labelEmail}</Radio>
</FormRadioGroupField>
{contactTypeValue === ContactType.Phone && phoneModel && (
<FormNumberInputField
model={phoneModel}
label="{i18n.labelPhone}"
required
/>
)}
{contactTypeValue === ContactType.Email && emailModel && (
<FormInputField model={emailModel} label="{i18n.labelEmail}" required />
)}
<div style={{ marginTop: 16 }}>
<Button type="primary" htmlType="submit" onClick={getFormValue}>
{i18n.printValue}
</Button>
<Checkbox
checked={preserveState}
onChange={onPreserveStateChange}
style={{ marginLeft: 16 }}
>
{i18n.preserveState}
</Checkbox>
</div>
</Form>
);
}
ReactDOM.render(<App />, mountNode);
```