This is page 49 of 52. Use http://codebase.md/alibaba/formily?lines=true&page={x} to view the full context. # Directory Structure ``` ├── .all-contributorsrc ├── .codecov.yml ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .github │ ├── CONTRIBUTING.md │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE │ │ └── config.yml │ ├── PULL_REQUEST_TEMPLATE.md │ └── workflows │ ├── check-pr-title.yml │ ├── ci.yml │ ├── commitlint.yml │ ├── issue-open-check.yml │ ├── package-size.yml │ └── pr-welcome.yml ├── .gitignore ├── .prettierrc.js ├── .umirc.js ├── .vscode │ └── cspell.json ├── .yarnrc ├── CHANGELOG.md ├── commitlint.config.js ├── devtools │ ├── .eslintrc │ └── chrome-extension │ ├── .npmignore │ ├── assets │ │ └── img │ │ ├── loading.svg │ │ └── logo │ │ ├── 128x128.png │ │ ├── 16x16.png │ │ ├── 38x38.png │ │ ├── 48x48.png │ │ ├── error.png │ │ ├── gray.png │ │ └── scalable.png │ ├── config │ │ ├── webpack.base.ts │ │ ├── webpack.dev.ts │ │ └── webpack.prod.ts │ ├── LICENSE.md │ ├── package.json │ ├── src │ │ ├── app │ │ │ ├── components │ │ │ │ ├── FieldTree.tsx │ │ │ │ ├── filter.ts │ │ │ │ ├── LeftPanel.tsx │ │ │ │ ├── RightPanel.tsx │ │ │ │ ├── SearchBox.tsx │ │ │ │ └── Tabs.tsx │ │ │ ├── demo.tsx │ │ │ └── index.tsx │ │ └── extension │ │ ├── backend.ts │ │ ├── background.ts │ │ ├── content.ts │ │ ├── devpanel.tsx │ │ ├── devtools.tsx │ │ ├── inject.ts │ │ ├── manifest.json │ │ ├── popup.tsx │ │ └── views │ │ ├── devpanel.ejs │ │ ├── devtools.ejs │ │ └── popup.ejs │ ├── tsconfig.build.json │ └── tsconfig.json ├── docs │ ├── functions │ │ ├── contributors.ts │ │ └── npm-search.ts │ ├── guide │ │ ├── advanced │ │ │ ├── async.md │ │ │ ├── async.zh-CN.md │ │ │ ├── build.md │ │ │ ├── build.zh-CN.md │ │ │ ├── business-logic.md │ │ │ ├── business-logic.zh-CN.md │ │ │ ├── calculator.md │ │ │ ├── calculator.zh-CN.md │ │ │ ├── controlled.md │ │ │ ├── controlled.zh-CN.md │ │ │ ├── custom.md │ │ │ ├── custom.zh-CN.md │ │ │ ├── destructor.md │ │ │ ├── destructor.zh-CN.md │ │ │ ├── input.less │ │ │ ├── layout.md │ │ │ ├── layout.zh-CN.md │ │ │ ├── linkages.md │ │ │ ├── linkages.zh-CN.md │ │ │ ├── validate.md │ │ │ └── validate.zh-CN.md │ │ ├── contribution.md │ │ ├── contribution.zh-CN.md │ │ ├── form-builder.md │ │ ├── form-builder.zh-CN.md │ │ ├── index.md │ │ ├── index.zh-CN.md │ │ ├── issue-helper.md │ │ ├── issue-helper.zh-CN.md │ │ ├── learn-formily.md │ │ ├── learn-formily.zh-CN.md │ │ ├── quick-start.md │ │ ├── quick-start.zh-CN.md │ │ ├── scenes │ │ │ ├── dialog-drawer.md │ │ │ ├── dialog-drawer.zh-CN.md │ │ │ ├── edit-detail.md │ │ │ ├── edit-detail.zh-CN.md │ │ │ ├── index.less │ │ │ ├── login-register.md │ │ │ ├── login-register.zh-CN.md │ │ │ ├── more.md │ │ │ ├── more.zh-CN.md │ │ │ ├── query-list.md │ │ │ ├── query-list.zh-CN.md │ │ │ ├── step-form.md │ │ │ ├── step-form.zh-CN.md │ │ │ ├── tab-form.md │ │ │ ├── tab-form.zh-CN.md │ │ │ └── VerifyCode.tsx │ │ ├── upgrade.md │ │ └── upgrade.zh-CN.md │ ├── index.md │ ├── index.zh-CN.md │ └── site │ ├── Contributors.less │ ├── Contributors.tsx │ ├── QrCode.less │ ├── QrCode.tsx │ ├── Section.less │ ├── Section.tsx │ └── styles.less ├── global.config.ts ├── jest.config.js ├── lerna.json ├── LICENSE.md ├── package.json ├── packages │ ├── .eslintrc │ ├── antd │ │ ├── __tests__ │ │ │ ├── moment.spec.ts │ │ │ └── sideEffects.spec.ts │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── build-style.ts │ │ ├── create-style.ts │ │ ├── docs │ │ │ ├── components │ │ │ │ ├── ArrayCards.md │ │ │ │ ├── ArrayCards.zh-CN.md │ │ │ │ ├── ArrayCollapse.md │ │ │ │ ├── ArrayCollapse.zh-CN.md │ │ │ │ ├── ArrayItems.md │ │ │ │ ├── ArrayItems.zh-CN.md │ │ │ │ ├── ArrayTable.md │ │ │ │ ├── ArrayTable.zh-CN.md │ │ │ │ ├── ArrayTabs.md │ │ │ │ ├── ArrayTabs.zh-CN.md │ │ │ │ ├── Cascader.md │ │ │ │ ├── Cascader.zh-CN.md │ │ │ │ ├── Checkbox.md │ │ │ │ ├── Checkbox.zh-CN.md │ │ │ │ ├── DatePicker.md │ │ │ │ ├── DatePicker.zh-CN.md │ │ │ │ ├── Editable.md │ │ │ │ ├── Editable.zh-CN.md │ │ │ │ ├── Form.md │ │ │ │ ├── Form.zh-CN.md │ │ │ │ ├── FormButtonGroup.md │ │ │ │ ├── FormButtonGroup.zh-CN.md │ │ │ │ ├── FormCollapse.md │ │ │ │ ├── FormCollapse.zh-CN.md │ │ │ │ ├── FormDialog.md │ │ │ │ ├── FormDialog.zh-CN.md │ │ │ │ ├── FormDrawer.md │ │ │ │ ├── FormDrawer.zh-CN.md │ │ │ │ ├── FormGrid.md │ │ │ │ ├── FormGrid.zh-CN.md │ │ │ │ ├── FormItem.md │ │ │ │ ├── FormItem.zh-CN.md │ │ │ │ ├── FormLayout.md │ │ │ │ ├── FormLayout.zh-CN.md │ │ │ │ ├── FormStep.md │ │ │ │ ├── FormStep.zh-CN.md │ │ │ │ ├── FormTab.md │ │ │ │ ├── FormTab.zh-CN.md │ │ │ │ ├── index.md │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── Input.md │ │ │ │ ├── Input.zh-CN.md │ │ │ │ ├── NumberPicker.md │ │ │ │ ├── NumberPicker.zh-CN.md │ │ │ │ ├── Password.md │ │ │ │ ├── Password.zh-CN.md │ │ │ │ ├── PreviewText.md │ │ │ │ ├── PreviewText.zh-CN.md │ │ │ │ ├── Radio.md │ │ │ │ ├── Radio.zh-CN.md │ │ │ │ ├── Reset.md │ │ │ │ ├── Reset.zh-CN.md │ │ │ │ ├── Select.md │ │ │ │ ├── Select.zh-CN.md │ │ │ │ ├── SelectTable.md │ │ │ │ ├── SelectTable.zh-CN.md │ │ │ │ ├── Space.md │ │ │ │ ├── Space.zh-CN.md │ │ │ │ ├── Submit.md │ │ │ │ ├── Submit.zh-CN.md │ │ │ │ ├── Switch.md │ │ │ │ ├── Switch.zh-CN.md │ │ │ │ ├── TimePicker.md │ │ │ │ ├── TimePicker.zh-CN.md │ │ │ │ ├── Transfer.md │ │ │ │ ├── Transfer.zh-CN.md │ │ │ │ ├── TreeSelect.md │ │ │ │ ├── TreeSelect.zh-CN.md │ │ │ │ ├── Upload.md │ │ │ │ └── Upload.zh-CN.md │ │ │ ├── index.md │ │ │ └── index.zh-CN.md │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __builtins__ │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── useClickAway.ts │ │ │ │ │ └── usePrefixCls.ts │ │ │ │ ├── index.ts │ │ │ │ ├── loading.ts │ │ │ │ ├── moment.ts │ │ │ │ ├── pickDataProps.ts │ │ │ │ ├── portal.tsx │ │ │ │ ├── render.ts │ │ │ │ └── sort.tsx │ │ │ ├── array-base │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-cards │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-collapse │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-items │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-table │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── array-tabs │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── cascader │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── checkbox │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── date-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── editable │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form-button-group │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form-collapse │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-dialog │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-drawer │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-grid │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form-item │ │ │ │ ├── animation.less │ │ │ │ ├── grid.less │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── form-layout │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ ├── style.ts │ │ │ │ └── useResponsiveFormLayout.ts │ │ │ ├── form-step │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-tab │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── index.ts │ │ │ ├── input │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── number-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── password │ │ │ │ ├── index.tsx │ │ │ │ ├── PasswordStrength.tsx │ │ │ │ └── style.ts │ │ │ ├── preview-text │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── radio │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ └── style.ts │ │ │ ├── reset │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── select │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── select-table │ │ │ │ ├── index.tsx │ │ │ │ ├── style.less │ │ │ │ ├── style.ts │ │ │ │ ├── useCheckSlackly.tsx │ │ │ │ ├── useFilterOptions.tsx │ │ │ │ ├── useFlatOptions.tsx │ │ │ │ ├── useSize.tsx │ │ │ │ ├── useTitleAddon.tsx │ │ │ │ └── utils.ts │ │ │ ├── space │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── style.less │ │ │ ├── style.ts │ │ │ ├── submit │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── switch │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── time-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── transfer │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── tree-select │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── upload │ │ │ ├── index.tsx │ │ │ ├── placeholder.ts │ │ │ └── style.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── benchmark │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── src │ │ │ └── index.tsx │ │ ├── template.ejs │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ ├── webpack.base.ts │ │ ├── webpack.dev.ts │ │ └── webpack.prod.ts │ ├── core │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── docs │ │ │ ├── api │ │ │ │ ├── entry │ │ │ │ │ ├── ActionResponse.less │ │ │ │ │ ├── ActionResponse.tsx │ │ │ │ │ ├── createForm.md │ │ │ │ │ ├── createForm.zh-CN.md │ │ │ │ │ ├── FieldEffectHooks.md │ │ │ │ │ ├── FieldEffectHooks.zh-CN.md │ │ │ │ │ ├── FormChecker.md │ │ │ │ │ ├── FormChecker.zh-CN.md │ │ │ │ │ ├── FormEffectHooks.md │ │ │ │ │ ├── FormEffectHooks.zh-CN.md │ │ │ │ │ ├── FormHooksAPI.md │ │ │ │ │ ├── FormHooksAPI.zh-CN.md │ │ │ │ │ ├── FormPath.md │ │ │ │ │ ├── FormPath.zh-CN.md │ │ │ │ │ ├── FormValidatorRegistry.md │ │ │ │ │ └── FormValidatorRegistry.zh-CN.md │ │ │ │ └── models │ │ │ │ ├── ArrayField.md │ │ │ │ ├── ArrayField.zh-CN.md │ │ │ │ ├── Field.md │ │ │ │ ├── Field.zh-CN.md │ │ │ │ ├── Form.md │ │ │ │ ├── Form.zh-CN.md │ │ │ │ ├── ObjectField.md │ │ │ │ ├── ObjectField.zh-CN.md │ │ │ │ ├── Query.md │ │ │ │ ├── Query.zh-CN.md │ │ │ │ ├── VoidField.md │ │ │ │ └── VoidField.zh-CN.md │ │ │ ├── guide │ │ │ │ ├── architecture.md │ │ │ │ ├── architecture.zh-CN.md │ │ │ │ ├── field.md │ │ │ │ ├── field.zh-CN.md │ │ │ │ ├── form.md │ │ │ │ ├── form.zh-CN.md │ │ │ │ ├── index.md │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── mvvm.md │ │ │ │ ├── mvvm.zh-CN.md │ │ │ │ ├── values.md │ │ │ │ └── values.zh-CN.md │ │ │ ├── index.md │ │ │ └── index.zh-CN.md │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── array.spec.ts │ │ │ │ ├── effects.spec.ts │ │ │ │ ├── externals.spec.ts │ │ │ │ ├── field.spec.ts │ │ │ │ ├── form.spec.ts │ │ │ │ ├── graph.spec.ts │ │ │ │ ├── heart.spec.ts │ │ │ │ ├── internals.spec.ts │ │ │ │ ├── lifecycle.spec.ts │ │ │ │ ├── object.spec.ts │ │ │ │ ├── shared.ts │ │ │ │ └── void.spec.ts │ │ │ ├── effects │ │ │ │ ├── index.ts │ │ │ │ ├── onFieldEffects.ts │ │ │ │ └── onFormEffects.ts │ │ │ ├── global.d.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── ArrayField.ts │ │ │ │ ├── BaseField.ts │ │ │ │ ├── Field.ts │ │ │ │ ├── Form.ts │ │ │ │ ├── Graph.ts │ │ │ │ ├── Heart.ts │ │ │ │ ├── index.ts │ │ │ │ ├── LifeCycle.ts │ │ │ │ ├── ObjectField.ts │ │ │ │ ├── Query.ts │ │ │ │ ├── types.ts │ │ │ │ └── VoidField.ts │ │ │ ├── shared │ │ │ │ ├── checkers.ts │ │ │ │ ├── constants.ts │ │ │ │ ├── effective.ts │ │ │ │ ├── externals.ts │ │ │ │ └── internals.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── element │ │ ├── .npmignore │ │ ├── build-style.ts │ │ ├── create-style.ts │ │ ├── docs │ │ │ ├── .vuepress │ │ │ │ ├── components │ │ │ │ │ ├── createCodeSandBox.js │ │ │ │ │ ├── dumi-previewer.vue │ │ │ │ │ └── highlight.js │ │ │ │ ├── config.js │ │ │ │ ├── enhanceApp.js │ │ │ │ ├── styles │ │ │ │ │ └── index.styl │ │ │ │ └── util.js │ │ │ ├── demos │ │ │ │ ├── guide │ │ │ │ │ ├── array-cards │ │ │ │ │ │ ├── effects-json-schema.vue │ │ │ │ │ │ ├── effects-markup-schema.vue │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── array-collapse │ │ │ │ │ │ ├── effects-json-schema.vue │ │ │ │ │ │ ├── effects-markup-schema.vue │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── array-items │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── array-table │ │ │ │ │ │ ├── effects-json-schema.vue │ │ │ │ │ │ ├── effects-markup-schema.vue │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── array-tabs │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── cascader │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── checkbox │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── date-picker │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── editable │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── form-button-group.vue │ │ │ │ │ ├── form-collapse │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── form-dialog │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── form-drawer │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── form-grid │ │ │ │ │ │ ├── form.vue │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── native.vue │ │ │ │ │ ├── form-item │ │ │ │ │ │ ├── bordered-none.vue │ │ │ │ │ │ ├── common.vue │ │ │ │ │ │ ├── feedback.vue │ │ │ │ │ │ ├── inset.vue │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ ├── size.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── form-layout │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── form-step │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── form-tab │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ └── markup-schema.vue │ │ │ │ │ ├── form.vue │ │ │ │ │ ├── input │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── input-number │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── password │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── preview-text │ │ │ │ │ │ ├── base.vue │ │ │ │ │ │ └── extend.vue │ │ │ │ │ ├── radio │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── reset │ │ │ │ │ │ ├── base.vue │ │ │ │ │ │ ├── force.vue │ │ │ │ │ │ └── validate.vue │ │ │ │ │ ├── select │ │ │ │ │ │ ├── json-schema-async.vue │ │ │ │ │ │ ├── json-schema-sync.vue │ │ │ │ │ │ ├── markup-schema-async-search.vue │ │ │ │ │ │ ├── markup-schema-async.vue │ │ │ │ │ │ ├── markup-schema-sync.vue │ │ │ │ │ │ ├── template-async.vue │ │ │ │ │ │ └── template-sync.vue │ │ │ │ │ ├── space │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── submit │ │ │ │ │ │ ├── base.vue │ │ │ │ │ │ └── loading.vue │ │ │ │ │ ├── switch │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── time-picker │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ ├── transfer │ │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ │ └── template.vue │ │ │ │ │ └── upload │ │ │ │ │ ├── json-schema.vue │ │ │ │ │ ├── markup-schema.vue │ │ │ │ │ └── template.vue │ │ │ │ └── index.vue │ │ │ ├── guide │ │ │ │ ├── array-cards.md │ │ │ │ ├── array-collapse.md │ │ │ │ ├── array-items.md │ │ │ │ ├── array-table.md │ │ │ │ ├── array-tabs.md │ │ │ │ ├── cascader.md │ │ │ │ ├── checkbox.md │ │ │ │ ├── date-picker.md │ │ │ │ ├── editable.md │ │ │ │ ├── form-button-group.md │ │ │ │ ├── form-collapse.md │ │ │ │ ├── form-dialog.md │ │ │ │ ├── form-drawer.md │ │ │ │ ├── form-grid.md │ │ │ │ ├── form-item.md │ │ │ │ ├── form-layout.md │ │ │ │ ├── form-step.md │ │ │ │ ├── form-tab.md │ │ │ │ ├── form.md │ │ │ │ ├── index.md │ │ │ │ ├── input-number.md │ │ │ │ ├── input.md │ │ │ │ ├── password.md │ │ │ │ ├── preview-text.md │ │ │ │ ├── radio.md │ │ │ │ ├── reset.md │ │ │ │ ├── select.md │ │ │ │ ├── space.md │ │ │ │ ├── submit.md │ │ │ │ ├── switch.md │ │ │ │ ├── time-picker.md │ │ │ │ ├── transfer.md │ │ │ │ └── upload.md │ │ │ └── README.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __builtins__ │ │ │ │ ├── configs │ │ │ │ │ └── index.ts │ │ │ │ ├── index.ts │ │ │ │ ├── shared │ │ │ │ │ ├── create-context.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── loading.ts │ │ │ │ │ ├── portal.ts │ │ │ │ │ ├── resolve-component.ts │ │ │ │ │ ├── transform-component.ts │ │ │ │ │ ├── types.ts │ │ │ │ │ └── utils.ts │ │ │ │ └── styles │ │ │ │ └── common.scss │ │ │ ├── array-base │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── array-cards │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── array-collapse │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── array-items │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── array-table │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── array-tabs │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── cascader │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── checkbox │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── date-picker │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── editable │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── el-form │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── el-form-item │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── form │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── form-button-group │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── form-collapse │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── form-dialog │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── form-drawer │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── form-grid │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── form-item │ │ │ │ ├── animation.scss │ │ │ │ ├── grid.scss │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ ├── style.ts │ │ │ │ └── var.scss │ │ │ ├── form-layout │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ ├── style.ts │ │ │ │ └── useResponsiveFormLayout.ts │ │ │ ├── form-step │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── form-tab │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── index.ts │ │ │ ├── input │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── input-number │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── password │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── preview-text │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── radio │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── reset │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── select │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── space │ │ │ │ ├── index.ts │ │ │ │ ├── style.scss │ │ │ │ └── style.ts │ │ │ ├── style.ts │ │ │ ├── submit │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── switch │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── time-picker │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ ├── transfer │ │ │ │ ├── index.ts │ │ │ │ └── style.ts │ │ │ └── upload │ │ │ ├── index.ts │ │ │ └── style.ts │ │ ├── transformer.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── grid │ │ ├── .npmignore │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── index.ts │ │ │ └── observer.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── json-schema │ │ ├── .npmignore │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── __snapshots__ │ │ │ │ │ └── schema.spec.ts.snap │ │ │ │ ├── compiler.spec.ts │ │ │ │ ├── patches.spec.ts │ │ │ │ ├── schema.spec.ts │ │ │ │ ├── server-validate.spec.ts │ │ │ │ ├── shared.spec.ts │ │ │ │ ├── transformer.spec.ts │ │ │ │ └── traverse.spec.ts │ │ │ ├── compiler.ts │ │ │ ├── global.d.ts │ │ │ ├── index.ts │ │ │ ├── patches.ts │ │ │ ├── polyfills │ │ │ │ ├── index.ts │ │ │ │ └── SPECIFICATION_1_0.ts │ │ │ ├── schema.ts │ │ │ ├── shared.ts │ │ │ ├── transformer.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── next │ │ ├── __tests__ │ │ │ ├── moment.spec.ts │ │ │ └── sideEffects.spec.ts │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── build-style.ts │ │ ├── create-style.ts │ │ ├── docs │ │ │ ├── components │ │ │ │ ├── ArrayCards.md │ │ │ │ ├── ArrayCards.zh-CN.md │ │ │ │ ├── ArrayCollapse.md │ │ │ │ ├── ArrayCollapse.zh-CN.md │ │ │ │ ├── ArrayItems.md │ │ │ │ ├── ArrayItems.zh-CN.md │ │ │ │ ├── ArrayTable.md │ │ │ │ ├── ArrayTable.zh-CN.md │ │ │ │ ├── Cascader.md │ │ │ │ ├── Cascader.zh-CN.md │ │ │ │ ├── Checkbox.md │ │ │ │ ├── Checkbox.zh-CN.md │ │ │ │ ├── DatePicker.md │ │ │ │ ├── DatePicker.zh-CN.md │ │ │ │ ├── DatePicker2.md │ │ │ │ ├── DatePicker2.zh-CN.md │ │ │ │ ├── Editable.md │ │ │ │ ├── Editable.zh-CN.md │ │ │ │ ├── Form.md │ │ │ │ ├── Form.zh-CN.md │ │ │ │ ├── FormButtonGroup.md │ │ │ │ ├── FormButtonGroup.zh-CN.md │ │ │ │ ├── FormCollapse.md │ │ │ │ ├── FormCollapse.zh-CN.md │ │ │ │ ├── FormDialog.md │ │ │ │ ├── FormDialog.zh-CN.md │ │ │ │ ├── FormDrawer.md │ │ │ │ ├── FormDrawer.zh-CN.md │ │ │ │ ├── FormGrid.md │ │ │ │ ├── FormGrid.zh-CN.md │ │ │ │ ├── FormItem.md │ │ │ │ ├── FormItem.zh-CN.md │ │ │ │ ├── FormLayout.md │ │ │ │ ├── FormLayout.zh-CN.md │ │ │ │ ├── FormStep.md │ │ │ │ ├── FormStep.zh-CN.md │ │ │ │ ├── FormTab.md │ │ │ │ ├── FormTab.zh-CN.md │ │ │ │ ├── index.md │ │ │ │ ├── index.zh-CN.md │ │ │ │ ├── Input.md │ │ │ │ ├── Input.zh-CN.md │ │ │ │ ├── NumberPicker.md │ │ │ │ ├── NumberPicker.zh-CN.md │ │ │ │ ├── Password.md │ │ │ │ ├── Password.zh-CN.md │ │ │ │ ├── PreviewText.md │ │ │ │ ├── PreviewText.zh-CN.md │ │ │ │ ├── Radio.md │ │ │ │ ├── Radio.zh-CN.md │ │ │ │ ├── Reset.md │ │ │ │ ├── Reset.zh-CN.md │ │ │ │ ├── Select.md │ │ │ │ ├── Select.zh-CN.md │ │ │ │ ├── SelectTable.md │ │ │ │ ├── SelectTable.zh-CN.md │ │ │ │ ├── Space.md │ │ │ │ ├── Space.zh-CN.md │ │ │ │ ├── Submit.md │ │ │ │ ├── Submit.zh-CN.md │ │ │ │ ├── Switch.md │ │ │ │ ├── Switch.zh-CN.md │ │ │ │ ├── TimePicker.md │ │ │ │ ├── TimePicker.zh-CN.md │ │ │ │ ├── TimePicker2.md │ │ │ │ ├── TimePicker2.zh-CN.md │ │ │ │ ├── Transfer.md │ │ │ │ ├── Transfer.zh-CN.md │ │ │ │ ├── TreeSelect.md │ │ │ │ ├── TreeSelect.zh-CN.md │ │ │ │ ├── Upload.md │ │ │ │ └── Upload.zh-CN.md │ │ │ ├── index.md │ │ │ └── index.zh-CN.md │ │ ├── LESENCE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __builtins__ │ │ │ │ ├── empty.tsx │ │ │ │ ├── hooks │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── useClickAway.ts │ │ │ │ │ └── usePrefixCls.ts │ │ │ │ ├── icons.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── loading.ts │ │ │ │ ├── mapSize.ts │ │ │ │ ├── mapStatus.ts │ │ │ │ ├── moment.ts │ │ │ │ ├── pickDataProps.ts │ │ │ │ ├── portal.tsx │ │ │ │ ├── render.ts │ │ │ │ └── toArray.ts │ │ │ ├── array-base │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── array-cards │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── array-collapse │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── array-items │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── array-table │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── cascader │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── checkbox │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── date-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── date-picker2 │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── editable │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── form │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── form-button-group │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── form-collapse │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-dialog │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-drawer │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-grid │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── form-item │ │ │ │ ├── animation.scss │ │ │ │ ├── grid.scss │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ ├── scss │ │ │ │ │ └── variable.scss │ │ │ │ └── style.ts │ │ │ ├── form-layout │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ ├── style.ts │ │ │ │ └── useResponsiveFormLayout.ts │ │ │ ├── form-step │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── form-tab │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── index.ts │ │ │ ├── input │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── main.scss │ │ │ ├── number-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── password │ │ │ │ ├── index.tsx │ │ │ │ ├── PasswordStrength.tsx │ │ │ │ └── style.ts │ │ │ ├── preview-text │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── radio │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── reset │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── select │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── select-table │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ ├── style.ts │ │ │ │ ├── useCheckSlackly.tsx │ │ │ │ ├── useFilterOptions.tsx │ │ │ │ ├── useFlatOptions.tsx │ │ │ │ ├── useSize.tsx │ │ │ │ ├── useTitleAddon.tsx │ │ │ │ └── utils.ts │ │ │ ├── space │ │ │ │ ├── index.tsx │ │ │ │ ├── main.scss │ │ │ │ └── style.ts │ │ │ ├── style.ts │ │ │ ├── submit │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── switch │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── time-picker │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── time-picker2 │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── transfer │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ ├── tree-select │ │ │ │ ├── index.tsx │ │ │ │ └── style.ts │ │ │ └── upload │ │ │ ├── index.tsx │ │ │ ├── main.scss │ │ │ ├── placeholder.ts │ │ │ └── style.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── path │ │ ├── .npmignore │ │ ├── benchmark.ts │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── accessor.spec.ts │ │ │ │ ├── basic.spec.ts │ │ │ │ ├── match.spec.ts │ │ │ │ ├── parser.spec.ts │ │ │ │ └── share.spec.ts │ │ │ ├── contexts.ts │ │ │ ├── destructor.ts │ │ │ ├── index.ts │ │ │ ├── matcher.ts │ │ │ ├── parser.ts │ │ │ ├── shared.ts │ │ │ ├── tokenizer.ts │ │ │ ├── tokens.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── react │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── docs │ │ │ ├── api │ │ │ │ ├── components │ │ │ │ │ ├── ArrayField.md │ │ │ │ │ ├── ArrayField.zh-CN.md │ │ │ │ │ ├── ExpressionScope.md │ │ │ │ │ ├── ExpressionScope.zh-CN.md │ │ │ │ │ ├── Field.md │ │ │ │ │ ├── Field.zh-CN.md │ │ │ │ │ ├── FormConsumer.md │ │ │ │ │ ├── FormConsumer.zh-CN.md │ │ │ │ │ ├── FormProvider.md │ │ │ │ │ ├── FormProvider.zh-CN.md │ │ │ │ │ ├── ObjectField.md │ │ │ │ │ ├── ObjectField.zh-CN.md │ │ │ │ │ ├── RecordScope.md │ │ │ │ │ ├── RecordScope.zh-CN.md │ │ │ │ │ ├── RecordsScope.md │ │ │ │ │ ├── RecordsScope.zh-CN.md │ │ │ │ │ ├── RecursionField.md │ │ │ │ │ ├── RecursionField.zh-CN.md │ │ │ │ │ ├── SchemaField.md │ │ │ │ │ ├── SchemaField.zh-CN.md │ │ │ │ │ ├── VoidField.md │ │ │ │ │ └── VoidField.zh-CN.md │ │ │ │ ├── hooks │ │ │ │ │ ├── useExpressionScope.md │ │ │ │ │ ├── useExpressionScope.zh-CN.md │ │ │ │ │ ├── useField.md │ │ │ │ │ ├── useField.zh-CN.md │ │ │ │ │ ├── useFieldSchema.md │ │ │ │ │ ├── useFieldSchema.zh-CN.md │ │ │ │ │ ├── useForm.md │ │ │ │ │ ├── useForm.zh-CN.md │ │ │ │ │ ├── useFormEffects.md │ │ │ │ │ ├── useFormEffects.zh-CN.md │ │ │ │ │ ├── useParentForm.md │ │ │ │ │ └── useParentForm.zh-CN.md │ │ │ │ └── shared │ │ │ │ ├── connect.md │ │ │ │ ├── connect.zh-CN.md │ │ │ │ ├── context.md │ │ │ │ ├── context.zh-CN.md │ │ │ │ ├── mapProps.md │ │ │ │ ├── mapProps.zh-CN.md │ │ │ │ ├── mapReadPretty.md │ │ │ │ ├── mapReadPretty.zh-CN.md │ │ │ │ ├── observer.md │ │ │ │ ├── observer.zh-CN.md │ │ │ │ ├── Schema.md │ │ │ │ └── Schema.zh-CN.md │ │ │ ├── guide │ │ │ │ ├── architecture.md │ │ │ │ ├── architecture.zh-CN.md │ │ │ │ ├── concept.md │ │ │ │ ├── concept.zh-CN.md │ │ │ │ ├── index.md │ │ │ │ └── index.zh-CN.md │ │ │ ├── index.md │ │ │ └── index.zh-CN.md │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── expression.spec.tsx │ │ │ │ ├── field.spec.tsx │ │ │ │ ├── form.spec.tsx │ │ │ │ ├── schema.json.spec.tsx │ │ │ │ ├── schema.markup.spec.tsx │ │ │ │ └── shared.tsx │ │ │ ├── components │ │ │ │ ├── ArrayField.tsx │ │ │ │ ├── ExpressionScope.tsx │ │ │ │ ├── Field.tsx │ │ │ │ ├── FormConsumer.tsx │ │ │ │ ├── FormProvider.tsx │ │ │ │ ├── index.ts │ │ │ │ ├── ObjectField.tsx │ │ │ │ ├── ReactiveField.tsx │ │ │ │ ├── RecordScope.tsx │ │ │ │ ├── RecordsScope.tsx │ │ │ │ ├── RecursionField.tsx │ │ │ │ ├── SchemaField.tsx │ │ │ │ └── VoidField.tsx │ │ │ ├── global.d.ts │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ ├── useAttach.ts │ │ │ │ ├── useExpressionScope.ts │ │ │ │ ├── useField.ts │ │ │ │ ├── useFieldSchema.ts │ │ │ │ ├── useForm.ts │ │ │ │ ├── useFormEffects.ts │ │ │ │ └── useParentForm.ts │ │ │ ├── index.ts │ │ │ ├── shared │ │ │ │ ├── connect.ts │ │ │ │ ├── context.ts │ │ │ │ ├── index.ts │ │ │ │ └── render.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── reactive │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── benchmark.ts │ │ ├── docs │ │ │ ├── api │ │ │ │ ├── action.md │ │ │ │ ├── action.zh-CN.md │ │ │ │ ├── autorun.md │ │ │ │ ├── autorun.zh-CN.md │ │ │ │ ├── batch.md │ │ │ │ ├── batch.zh-CN.md │ │ │ │ ├── define.md │ │ │ │ ├── define.zh-CN.md │ │ │ │ ├── hasCollected.md │ │ │ │ ├── hasCollected.zh-CN.md │ │ │ │ ├── markObservable.md │ │ │ │ ├── markObservable.zh-CN.md │ │ │ │ ├── markRaw.md │ │ │ │ ├── markRaw.zh-CN.md │ │ │ │ ├── model.md │ │ │ │ ├── model.zh-CN.md │ │ │ │ ├── observable.md │ │ │ │ ├── observable.zh-CN.md │ │ │ │ ├── observe.md │ │ │ │ ├── observe.zh-CN.md │ │ │ │ ├── raw.md │ │ │ │ ├── raw.zh-CN.md │ │ │ │ ├── react │ │ │ │ │ ├── observer.md │ │ │ │ │ └── observer.zh-CN.md │ │ │ │ ├── reaction.md │ │ │ │ ├── reaction.zh-CN.md │ │ │ │ ├── toJS.md │ │ │ │ ├── toJS.zh-CN.md │ │ │ │ ├── tracker.md │ │ │ │ ├── tracker.zh-CN.md │ │ │ │ ├── typeChecker.md │ │ │ │ ├── typeChecker.zh-CN.md │ │ │ │ ├── untracked.md │ │ │ │ ├── untracked.zh-CN.md │ │ │ │ └── vue │ │ │ │ ├── observer.md │ │ │ │ └── observer.zh-CN.md │ │ │ ├── guide │ │ │ │ ├── best-practice.md │ │ │ │ ├── best-practice.zh-CN.md │ │ │ │ ├── concept.md │ │ │ │ ├── concept.zh-CN.md │ │ │ │ ├── index.md │ │ │ │ └── index.zh-CN.md │ │ │ ├── index.md │ │ │ └── index.zh-CN.md │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── action.spec.ts │ │ │ │ ├── annotations.spec.ts │ │ │ │ ├── array.spec.ts │ │ │ │ ├── autorun.spec.ts │ │ │ │ ├── batch.spec.ts │ │ │ │ ├── collections-map.spec.ts │ │ │ │ ├── collections-set.spec.ts │ │ │ │ ├── collections-weakmap.spec.ts │ │ │ │ ├── collections-weakset.spec.ts │ │ │ │ ├── define.spec.ts │ │ │ │ ├── externals.spec.ts │ │ │ │ ├── hasCollected.spec.ts │ │ │ │ ├── observable.spec.ts │ │ │ │ ├── observe.spec.ts │ │ │ │ ├── tracker.spec.ts │ │ │ │ └── untracked.spec.ts │ │ │ ├── action.ts │ │ │ ├── annotations │ │ │ │ ├── box.ts │ │ │ │ ├── computed.ts │ │ │ │ ├── index.ts │ │ │ │ ├── observable.ts │ │ │ │ ├── ref.ts │ │ │ │ └── shallow.ts │ │ │ ├── array.ts │ │ │ ├── autorun.ts │ │ │ ├── batch.ts │ │ │ ├── checkers.ts │ │ │ ├── environment.ts │ │ │ ├── externals.ts │ │ │ ├── global.d.ts │ │ │ ├── handlers.ts │ │ │ ├── index.ts │ │ │ ├── internals.ts │ │ │ ├── model.ts │ │ │ ├── observable.ts │ │ │ ├── observe.ts │ │ │ ├── reaction.ts │ │ │ ├── tracker.ts │ │ │ ├── tree.ts │ │ │ ├── types.ts │ │ │ └── untracked.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── reactive-react │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ ├── useCompatEffect.ts │ │ │ │ ├── useCompatFactory.ts │ │ │ │ ├── useDidUpdate.ts │ │ │ │ ├── useForceUpdate.ts │ │ │ │ ├── useLayoutEffect.ts │ │ │ │ └── useObserver.ts │ │ │ ├── index.ts │ │ │ ├── observer.ts │ │ │ ├── shared │ │ │ │ ├── gc.ts │ │ │ │ ├── global.ts │ │ │ │ ├── immediate.ts │ │ │ │ └── index.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── reactive-test-cases-for-react18 │ │ ├── .npmignore │ │ ├── .umirc.js │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── src │ │ │ ├── index.js │ │ │ └── MySlowList.js │ │ ├── template.ejs │ │ ├── tsconfig.build.json │ │ ├── tsconfig.json │ │ ├── webpack.base.ts │ │ ├── webpack.dev.ts │ │ └── webpack.prod.ts │ ├── reactive-vue │ │ ├── .npmignore │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ └── observer.spec.ts │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ └── useObserver.ts │ │ │ ├── index.ts │ │ │ ├── observer │ │ │ │ ├── collectData.ts │ │ │ │ ├── index.ts │ │ │ │ ├── observerInVue2.ts │ │ │ │ └── observerInVue3.ts │ │ │ └── types.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── shared │ │ ├── .npmignore │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ └── index.spec.ts │ │ │ ├── array.ts │ │ │ ├── case.ts │ │ │ ├── checkers.ts │ │ │ ├── clone.ts │ │ │ ├── compare.ts │ │ │ ├── defaults.ts │ │ │ ├── deprecate.ts │ │ │ ├── global.ts │ │ │ ├── index.ts │ │ │ ├── instanceof.ts │ │ │ ├── isEmpty.ts │ │ │ ├── merge.ts │ │ │ ├── middleware.ts │ │ │ ├── path.ts │ │ │ ├── string.ts │ │ │ ├── subscribable.ts │ │ │ └── uid.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ ├── validator │ │ ├── .npmignore │ │ ├── LICENSE.md │ │ ├── package.json │ │ ├── README.md │ │ ├── rollup.config.js │ │ ├── src │ │ │ ├── __tests__ │ │ │ │ ├── parser.spec.ts │ │ │ │ ├── registry.spec.ts │ │ │ │ └── validator.spec.ts │ │ │ ├── formats.ts │ │ │ ├── index.ts │ │ │ ├── locale.ts │ │ │ ├── parser.ts │ │ │ ├── registry.ts │ │ │ ├── rules.ts │ │ │ ├── template.ts │ │ │ ├── types.ts │ │ │ └── validator.ts │ │ ├── tsconfig.build.json │ │ └── tsconfig.json │ └── vue │ ├── .npmignore │ ├── bin │ │ ├── formily-vue-fix.js │ │ └── formily-vue-switch.js │ ├── docs │ │ ├── .vuepress │ │ │ ├── components │ │ │ │ ├── createCodeSandBox.js │ │ │ │ ├── dumi-previewer.vue │ │ │ │ └── highlight.js │ │ │ ├── config.js │ │ │ ├── enhanceApp.js │ │ │ └── styles │ │ │ └── index.styl │ │ ├── api │ │ │ ├── components │ │ │ │ ├── array-field.md │ │ │ │ ├── expression-scope.md │ │ │ │ ├── field.md │ │ │ │ ├── form-consumer.md │ │ │ │ ├── form-provider.md │ │ │ │ ├── object-field.md │ │ │ │ ├── recursion-field-with-component.md │ │ │ │ ├── recursion-field.md │ │ │ │ ├── schema-field-with-schema.md │ │ │ │ ├── schema-field.md │ │ │ │ └── void-field.md │ │ │ ├── hooks │ │ │ │ ├── use-field-schema.md │ │ │ │ ├── use-field.md │ │ │ │ ├── use-form-effects.md │ │ │ │ ├── use-form.md │ │ │ │ └── use-parent-form.md │ │ │ └── shared │ │ │ ├── connect.md │ │ │ ├── injections.md │ │ │ ├── map-props.md │ │ │ ├── map-read-pretty.md │ │ │ ├── observer.md │ │ │ └── schema.md │ │ ├── demos │ │ │ ├── api │ │ │ │ ├── components │ │ │ │ │ ├── array-field.vue │ │ │ │ │ ├── expression-scope.vue │ │ │ │ │ ├── field.vue │ │ │ │ │ ├── form-consumer.vue │ │ │ │ │ ├── form-provider.vue │ │ │ │ │ ├── object-field.vue │ │ │ │ │ ├── recursion-field-with-component.vue │ │ │ │ │ ├── recursion-field.vue │ │ │ │ │ ├── schema-field-with-schema.vue │ │ │ │ │ ├── schema-field.vue │ │ │ │ │ └── void-field.vue │ │ │ │ ├── hooks │ │ │ │ │ ├── use-field-schema.vue │ │ │ │ │ ├── use-field.vue │ │ │ │ │ ├── use-form-effects.vue │ │ │ │ │ ├── use-form.vue │ │ │ │ │ └── use-parent-form.vue │ │ │ │ └── shared │ │ │ │ ├── connect.vue │ │ │ │ ├── map-props.vue │ │ │ │ ├── map-read-pretty.vue │ │ │ │ └── observer.vue │ │ │ ├── index.vue │ │ │ └── questions │ │ │ ├── default-slot.vue │ │ │ ├── events.vue │ │ │ ├── named-slot.vue │ │ │ └── scoped-slot.vue │ │ ├── guide │ │ │ ├── architecture.md │ │ │ ├── concept.md │ │ │ └── README.md │ │ ├── questions │ │ │ └── README.md │ │ └── README.md │ ├── package.json │ ├── README.md │ ├── rollup.config.js │ ├── scripts │ │ ├── postinstall.js │ │ ├── switch-cli.js │ │ └── utils.js │ ├── src │ │ ├── __tests__ │ │ │ ├── expression.scope.spec.ts │ │ │ ├── field.spec.ts │ │ │ ├── form.spec.ts │ │ │ ├── schema.json.spec.ts │ │ │ ├── schema.markup.spec.ts │ │ │ ├── shared.spec.ts │ │ │ └── utils.spec.ts │ │ ├── components │ │ │ ├── ArrayField.ts │ │ │ ├── ExpressionScope.ts │ │ │ ├── Field.ts │ │ │ ├── FormConsumer.ts │ │ │ ├── FormProvider.ts │ │ │ ├── index.ts │ │ │ ├── ObjectField.ts │ │ │ ├── ReactiveField.ts │ │ │ ├── RecursionField.ts │ │ │ ├── SchemaField.ts │ │ │ └── VoidField.ts │ │ ├── global.d.ts │ │ ├── hooks │ │ │ ├── index.ts │ │ │ ├── useAttach.ts │ │ │ ├── useField.ts │ │ │ ├── useFieldSchema.ts │ │ │ ├── useForm.ts │ │ │ ├── useFormEffects.ts │ │ │ ├── useInjectionCleaner.ts │ │ │ └── useParentForm.ts │ │ ├── index.ts │ │ ├── shared │ │ │ ├── connect.ts │ │ │ ├── context.ts │ │ │ ├── createForm.ts │ │ │ ├── fragment.ts │ │ │ ├── h.ts │ │ │ └── index.ts │ │ ├── types │ │ │ └── index.ts │ │ ├── utils │ │ │ ├── formatVNodeData.ts │ │ │ ├── getFieldProps.ts │ │ │ ├── getRawComponent.ts │ │ │ └── resolveSchemaProps.ts │ │ └── vue2-components.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ └── tsconfig.types.json ├── README.md ├── README.zh-cn.md ├── scripts │ ├── build-style │ │ ├── buildAllStyles.ts │ │ ├── copy.ts │ │ ├── helper.ts │ │ └── index.ts │ └── rollup.base.js ├── tsconfig.build.json ├── tsconfig.jest.json ├── tsconfig.json └── yarn.lock ``` # Files -------------------------------------------------------------------------------- /docs/guide/advanced/validate.md: -------------------------------------------------------------------------------- ```markdown 1 | # Form Validation 2 | 3 | Formily's form validation uses the extremely powerful and flexible @formily/validator validation engine. There are two main scenarios for validation: 4 | 5 | - Markup(JSON) Schema scene protocol verification property verification, using JSON Schema's own verification property and x-validator property to achieve verification 6 | - Pure JSX scene verification properties, use validator property to achieve verification 7 | 8 | At the same time, we can also implement linkage verification in effects or x-reactions/reactions 9 | 10 | Specific rule verification document reference [FieldValidator](https://core.formilyjs.org/api/models/field#fieldvalidator) 11 | 12 | Form validation is an important part of optimizing user experience and ensuring data accuracy in forms. Formily provides various validation methods, including built-in rule validation, built-in format validation, and custom rule validation. In the following sections, we will introduce these validation methods one by one. 13 | 14 | ## Built-in rule check 15 | 16 | Built-in rule validation refers to the common validation rules provided by Formily, such as required, max, min, len, enum, const, multipleOf, etc. These rules can be described using JSON Schema properties or the x-validator property. Formily supports multiple ways of writing built-in rules and it is recommended for teams to establish internal conventions based on their usage habits. 17 | 18 | #### Markup Schema Use Cases 19 | 20 | ```tsx 21 | import React from 'react' 22 | import { createForm } from '@formily/core' 23 | import { createSchemaField } from '@formily/react' 24 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 25 | 26 | const form = createForm() 27 | 28 | const SchemaField = createSchemaField({ 29 | components: { 30 | Input, 31 | FormItem, 32 | NumberPicker, 33 | }, 34 | }) 35 | 36 | export default () => ( 37 | <Form form={form} labelCol={6} wrapperCol={10}> 38 | <SchemaField> 39 | <SchemaField.String 40 | name="required_1" 41 | title="Required" 42 | required 43 | x-component="Input" 44 | x-decorator="FormItem" 45 | /> 46 | <SchemaField.String 47 | name="required_2" 48 | title="Required" 49 | x-validator={{ required: true }} 50 | x-component="Input" 51 | x-decorator="FormItem" 52 | /> 53 | <SchemaField.String 54 | name="required_3" 55 | title="Required" 56 | x-validator={[{ required: true }]} 57 | x-component="Input" 58 | x-decorator="FormItem" 59 | /> 60 | <SchemaField.Number 61 | name="max_1" 62 | title="Maximum value (>5 error)" 63 | maximum={5} 64 | x-component="NumberPicker" 65 | x-decorator="FormItem" 66 | /> 67 | <SchemaField.Number 68 | name="max_2" 69 | title="Maximum value (>5 error)" 70 | x-validator={{ maximum: 5 }} 71 | x-component="NumberPicker" 72 | x-decorator="FormItem" 73 | /> 74 | <SchemaField.Number 75 | name="max_3" 76 | title="Maximum value (>5 error)" 77 | x-validator={[{ maximum: 5 }]} 78 | x-component="NumberPicker" 79 | x-decorator="FormItem" 80 | /> 81 | <SchemaField.Number 82 | name="max_4" 83 | title="Maximum value (>=5 error)" 84 | exclusiveMaximum={5} 85 | x-component="NumberPicker" 86 | x-decorator="FormItem" 87 | /> 88 | <SchemaField.Number 89 | name="max_5" 90 | title="Maximum value (>=5 error)" 91 | x-validator={{ exclusiveMaximum: 5 }} 92 | x-component="NumberPicker" 93 | x-decorator="FormItem" 94 | /> 95 | <SchemaField.Number 96 | name="max_6" 97 | title="Maximum value (>=5 error)" 98 | x-validator={[{ exclusiveMaximum: 5 }]} 99 | x-component="NumberPicker" 100 | x-decorator="FormItem" 101 | /> 102 | 103 | <SchemaField.Number 104 | name="min_1" 105 | title="Minimum value (<5 error)" 106 | minimum={5} 107 | x-component="NumberPicker" 108 | x-decorator="FormItem" 109 | /> 110 | <SchemaField.Number 111 | name="min_2" 112 | title="Minimum value (<5 error)" 113 | x-validator={{ minimum: 5 }} 114 | x-component="NumberPicker" 115 | x-decorator="FormItem" 116 | /> 117 | <SchemaField.Number 118 | name="min_3" 119 | title="Minimum value (<5 error)" 120 | x-validator={[{ minimum: 5 }]} 121 | x-component="NumberPicker" 122 | x-decorator="FormItem" 123 | /> 124 | <SchemaField.Number 125 | name="min_4" 126 | title="Minimum value (<=5 error)" 127 | exclusiveMinimum={5} 128 | x-component="NumberPicker" 129 | x-decorator="FormItem" 130 | /> 131 | <SchemaField.Number 132 | name="min_5" 133 | title="Minimum value (<=5 error)" 134 | x-validator={{ exclusiveMinimum: 5 }} 135 | x-component="NumberPicker" 136 | x-decorator="FormItem" 137 | /> 138 | <SchemaField.Number 139 | name="min_6" 140 | title="Minimum value (<=5 error)" 141 | x-validator={[{ exclusiveMinimum: 5 }]} 142 | x-component="NumberPicker" 143 | x-decorator="FormItem" 144 | /> 145 | 146 | <SchemaField.String 147 | name="length_1" 148 | title="Length is 5" 149 | x-validator={{ len: 5 }} 150 | x-component="Input" 151 | x-decorator="FormItem" 152 | /> 153 | <SchemaField.String 154 | name="length_2" 155 | title="Length is 5" 156 | x-validator={[{ len: 5 }]} 157 | x-component="Input" 158 | x-decorator="FormItem" 159 | /> 160 | 161 | <SchemaField.String 162 | name="maxlength_1" 163 | title="Maximum length is 5" 164 | maxLength={5} 165 | x-component="Input" 166 | x-decorator="FormItem" 167 | /> 168 | <SchemaField.String 169 | name="maxlength_2" 170 | title="Maximum length is 5" 171 | x-validator={{ max: 5 }} 172 | x-component="Input" 173 | x-decorator="FormItem" 174 | /> 175 | <SchemaField.String 176 | name="maxlength_3" 177 | title="Maximum length is 5" 178 | x-validator={[{ max: 5 }]} 179 | x-component="Input" 180 | x-decorator="FormItem" 181 | /> 182 | 183 | <SchemaField.String 184 | name="maxlength_4" 185 | title="Minimum length is 5" 186 | minLength={5} 187 | x-component="Input" 188 | x-decorator="FormItem" 189 | /> 190 | <SchemaField.String 191 | name="maxlength_5" 192 | title="Minimum length is 5" 193 | x-validator={{ min: 5 }} 194 | x-component="Input" 195 | x-decorator="FormItem" 196 | /> 197 | <SchemaField.String 198 | name="maxlength_6" 199 | title="Minimum length is 5" 200 | x-validator={[{ min: 5 }]} 201 | x-component="Input" 202 | x-decorator="FormItem" 203 | /> 204 | 205 | <SchemaField.String 206 | name="whitespace" 207 | title="Exclude pure whitespace characters" 208 | x-validator={[{ whitespace: true }]} 209 | x-component="Input" 210 | x-decorator="FormItem" 211 | /> 212 | 213 | <SchemaField.String 214 | name="enum" 215 | title="Enumeration match" 216 | x-validator={[{ enum: ['1', '2', '3'] }]} 217 | x-component="Input" 218 | x-decorator="FormItem" 219 | /> 220 | 221 | <SchemaField.String 222 | name="const" 223 | title="Constant match" 224 | const="123" 225 | x-component="Input" 226 | x-decorator="FormItem" 227 | /> 228 | 229 | <SchemaField.String 230 | name="multipleOf" 231 | title="Divisible match" 232 | multipleOf={2} 233 | x-component="NumberPicker" 234 | x-decorator="FormItem" 235 | /> 236 | </SchemaField> 237 | </Form> 238 | ) 239 | ``` 240 | 241 | #### JSON Schema Use Cases 242 | 243 | ```tsx 244 | import React from 'react' 245 | import { createForm } from '@formily/core' 246 | import { createSchemaField } from '@formily/react' 247 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 248 | 249 | const form = createForm() 250 | 251 | const SchemaField = createSchemaField({ 252 | components: { 253 | Input, 254 | FormItem, 255 | NumberPicker, 256 | }, 257 | }) 258 | 259 | const schema = { 260 | type: 'object', 261 | properties: { 262 | required_1: { 263 | name: 'required_1', 264 | title: 'Required', 265 | type: 'string', 266 | required: true, 267 | 'x-decorator': 'FormItem', 268 | 'x-component': 'Input', 269 | }, 270 | required_2: { 271 | name: 'required_2', 272 | title: 'Required', 273 | type: 'string', 274 | 'x-validator': { 275 | required: true, 276 | }, 277 | 'x-decorator': 'FormItem', 278 | 'x-component': 'Input', 279 | }, 280 | required_3: { 281 | name: 'required_3', 282 | title: 'Required', 283 | type: 'string', 284 | 'x-validator': [ 285 | { 286 | required: true, 287 | }, 288 | ], 289 | 'x-decorator': 'FormItem', 290 | 'x-component': 'Input', 291 | }, 292 | max_1: { 293 | name: 'max_1', 294 | title: 'Maximum value (>5 error)', 295 | type: 'number', 296 | maximum: 5, 297 | 'x-decorator': 'FormItem', 298 | 'x-component': 'NumberPicker', 299 | }, 300 | max_2: { 301 | name: 'max_2', 302 | title: 'Maximum value (>5 error)', 303 | type: 'number', 304 | 'x-validator': { 305 | maximum: 5, 306 | }, 307 | 'x-decorator': 'FormItem', 308 | 'x-component': 'NumberPicker', 309 | }, 310 | max_3: { 311 | name: 'max_3', 312 | title: 'Maximum value (>5 error)', 313 | type: 'number', 314 | 'x-validator': [ 315 | { 316 | maximum: 5, 317 | }, 318 | ], 319 | 'x-decorator': 'FormItem', 320 | 'x-component': 'NumberPicker', 321 | }, 322 | max_4: { 323 | name: 'max_4', 324 | title: 'Maximum value (>=5 error))', 325 | type: 'number', 326 | exclusiveMaximum: 5, 327 | 'x-decorator': 'FormItem', 328 | 'x-component': 'NumberPicker', 329 | }, 330 | max_5: { 331 | name: 'max_5', 332 | title: 'Maximum value (>=5 error))', 333 | type: 'number', 334 | 'x-validator': { 335 | exclusiveMaximum: 5, 336 | }, 337 | 'x-decorator': 'FormItem', 338 | 'x-component': 'NumberPicker', 339 | }, 340 | max_6: { 341 | name: 'max_6', 342 | title: 'Maximum value (>=5 error))', 343 | type: 'number', 344 | 'x-validator': [ 345 | { 346 | exclusiveMaximum: 5, 347 | }, 348 | ], 349 | 'x-decorator': 'FormItem', 350 | 'x-component': 'NumberPicker', 351 | }, 352 | min_1: { 353 | name: 'min_1', 354 | title: 'Minimum value (<5 error))', 355 | type: 'number', 356 | minimum: 5, 357 | 'x-decorator': 'FormItem', 358 | 'x-component': 'NumberPicker', 359 | }, 360 | min_2: { 361 | name: 'min_2', 362 | title: 'Minimum value (<5 error))', 363 | type: 'number', 364 | 'x-validator': { 365 | minimum: 5, 366 | }, 367 | 'x-decorator': 'FormItem', 368 | 'x-component': 'NumberPicker', 369 | }, 370 | min_3: { 371 | name: 'min_3', 372 | title: 'Minimum value (<5 error))', 373 | type: 'string', 374 | 'x-validator': [ 375 | { 376 | minimum: 5, 377 | }, 378 | ], 379 | 'x-decorator': 'FormItem', 380 | 'x-component': 'NumberPicker', 381 | }, 382 | min_4: { 383 | name: 'min_4', 384 | title: 'Minimum value (<=5 error))', 385 | type: 'number', 386 | exclusiveMinimum: 5, 387 | 'x-decorator': 'FormItem', 388 | 'x-component': 'NumberPicker', 389 | }, 390 | min_5: { 391 | name: 'min_5', 392 | title: 'Minimum value (<=5 error))', 393 | type: 'number', 394 | 'x-validator': { 395 | exclusiveMinimum: 5, 396 | }, 397 | 'x-decorator': 'FormItem', 398 | 'x-component': 'NumberPicker', 399 | }, 400 | min_6: { 401 | name: 'min_6', 402 | title: 'Minimum value (<=5 error))', 403 | type: 'number', 404 | 'x-validator': [ 405 | { 406 | exclusiveMinimum: 5, 407 | }, 408 | ], 409 | 'x-decorator': 'FormItem', 410 | 'x-component': 'NumberPicker', 411 | }, 412 | length_1: { 413 | name: 'length_1', 414 | title: 'Length is 5', 415 | type: 'string', 416 | 'x-validator': { 417 | len: 5, 418 | }, 419 | 'x-decorator': 'FormItem', 420 | 'x-component': 'Input', 421 | }, 422 | length_2: { 423 | name: 'length_2', 424 | title: 'Length is 5', 425 | type: 'string', 426 | 'x-validator': [ 427 | { 428 | len: 5, 429 | }, 430 | ], 431 | 'x-decorator': 'FormItem', 432 | 'x-component': 'Input', 433 | }, 434 | maxlength_1: { 435 | name: 'maxlength_1', 436 | title: 'Maximum length is 5', 437 | type: 'string', 438 | maxLength: 5, 439 | 'x-decorator': 'FormItem', 440 | 'x-component': 'Input', 441 | }, 442 | maxlength_2: { 443 | name: 'maxlength_2', 444 | title: 'Maximum length is 5', 445 | type: 'string', 446 | 'x-validator': { 447 | max: 5, 448 | }, 449 | 'x-decorator': 'FormItem', 450 | 'x-component': 'Input', 451 | }, 452 | maxlength_3: { 453 | name: 'maxlength_3', 454 | title: 'Maximum length is 5', 455 | type: 'string', 456 | 'x-validator': [ 457 | { 458 | max: 5, 459 | }, 460 | ], 461 | 'x-decorator': 'FormItem', 462 | 'x-component': 'Input', 463 | }, 464 | minlength_1: { 465 | name: 'minlength_1', 466 | title: 'Minimum length is 5', 467 | type: 'string', 468 | minLength: 5, 469 | 'x-decorator': 'FormItem', 470 | 'x-component': 'Input', 471 | }, 472 | minlength_2: { 473 | name: 'minlength_2', 474 | title: 'Minimum length is 5', 475 | type: 'string', 476 | 'x-validator': { 477 | min: 5, 478 | }, 479 | 'x-decorator': 'FormItem', 480 | 'x-component': 'Input', 481 | }, 482 | minlength_3: { 483 | name: 'minlength_3', 484 | title: 'Minimum length is 5', 485 | type: 'string', 486 | 'x-validator': [ 487 | { 488 | min: 5, 489 | }, 490 | ], 491 | 'x-decorator': 'FormItem', 492 | 'x-component': 'Input', 493 | }, 494 | whitespace: { 495 | name: 'whitespace', 496 | title: 'Exclude pure whitespace characters', 497 | type: 'string', 498 | 'x-validator': [ 499 | { 500 | whitespace: true, 501 | }, 502 | ], 503 | 'x-decorator': 'FormItem', 504 | 'x-component': 'Input', 505 | }, 506 | enum: { 507 | name: 'enum', 508 | title: 'Enumeration match', 509 | type: 'string', 510 | 'x-validator': [ 511 | { 512 | enum: ['1', '2', '3'], 513 | }, 514 | ], 515 | 'x-decorator': 'FormItem', 516 | 'x-component': 'Input', 517 | }, 518 | const: { 519 | name: 'const', 520 | title: 'Constant match', 521 | type: 'string', 522 | const: '123', 523 | 'x-decorator': 'FormItem', 524 | 'x-component': 'Input', 525 | }, 526 | multipleOf: { 527 | name: 'multipleOf', 528 | title: 'Divisible match', 529 | type: 'string', 530 | multipleOf: 2, 531 | 'x-decorator': 'FormItem', 532 | 'x-component': 'NumberPicker', 533 | }, 534 | }, 535 | } 536 | 537 | export default () => ( 538 | <Form form={form} labelCol={6} wrapperCol={10}> 539 | <SchemaField schema={schema} /> 540 | </Form> 541 | ) 542 | ``` 543 | 544 | #### Pure JSX Case 545 | 546 | ```tsx 547 | import React from 'react' 548 | import { createForm } from '@formily/core' 549 | import { Field } from '@formily/react' 550 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 551 | 552 | const form = createForm() 553 | 554 | export default () => ( 555 | <Form form={form} labelCol={6} wrapperCol={10}> 556 | <Field 557 | name="required_1" 558 | title="Required" 559 | required 560 | component={[Input]} 561 | decorator={[FormItem]} 562 | /> 563 | <Field 564 | name="required_2" 565 | title="Required" 566 | validator={{ required: true }} 567 | component={[Input]} 568 | decorator={[FormItem]} 569 | /> 570 | <Field 571 | name="required_3" 572 | title="Required" 573 | validator={[{ required: true }]} 574 | component={[Input]} 575 | decorator={[FormItem]} 576 | /> 577 | <Field 578 | name="max_1" 579 | title="Maximum value (>5 error)" 580 | validator={{ maximum: 5 }} 581 | component={[NumberPicker]} 582 | decorator={[FormItem]} 583 | /> 584 | <Field 585 | name="max_2" 586 | title="Maximum value (>5 error)" 587 | validator={[{ maximum: 5 }]} 588 | component={[NumberPicker]} 589 | decorator={[FormItem]} 590 | /> 591 | <Field 592 | name="max_3" 593 | title="Maximum value (>=5 error)" 594 | validator={{ exclusiveMaximum: 5 }} 595 | component={[NumberPicker]} 596 | decorator={[FormItem]} 597 | /> 598 | <Field 599 | name="max_4" 600 | title="Maximum value (>=5 error)" 601 | validator={[{ exclusiveMaximum: 5 }]} 602 | component={[NumberPicker]} 603 | decorator={[FormItem]} 604 | /> 605 | <Field 606 | name="min_1" 607 | title="Minimum value (<5 error)" 608 | validator={{ minimum: 5 }} 609 | component={[NumberPicker]} 610 | decorator={[FormItem]} 611 | /> 612 | <Field 613 | name="min_2" 614 | title="Minimum value (<5 error)" 615 | validator={[{ minimum: 5 }]} 616 | component={[NumberPicker]} 617 | decorator={[FormItem]} 618 | /> 619 | <Field 620 | name="min_3" 621 | title="Minimum value (<=5 error)" 622 | validator={{ exclusiveMinimum: 5 }} 623 | component={[NumberPicker]} 624 | decorator={[FormItem]} 625 | /> 626 | <Field 627 | name="min_4" 628 | title="Minimum value (<=5 error)" 629 | validator={[{ exclusiveMinimum: 5 }]} 630 | component={[NumberPicker]} 631 | decorator={[FormItem]} 632 | /> 633 | 634 | <Field 635 | name="length_1" 636 | title="Length is 5" 637 | validator={{ len: 5 }} 638 | component={[Input]} 639 | decorator={[FormItem]} 640 | /> 641 | <Field 642 | name="length_2" 643 | title="Length is 5" 644 | validator={[{ len: 5 }]} 645 | component={[Input]} 646 | decorator={[FormItem]} 647 | /> 648 | <Field 649 | name="maxlength_1" 650 | title="Maximum length is 5" 651 | validator={{ max: 5 }} 652 | component={[Input]} 653 | decorator={[FormItem]} 654 | /> 655 | <Field 656 | name="maxlength_2" 657 | title="Maximum length is 5" 658 | validator={[{ max: 5 }]} 659 | component={[Input]} 660 | decorator={[FormItem]} 661 | /> 662 | <Field 663 | name="minlength_1" 664 | title="Minimum length is 5" 665 | validator={{ min: 5 }} 666 | component={[Input]} 667 | decorator={[FormItem]} 668 | /> 669 | <Field 670 | name="minlength_2" 671 | title="Minimum length is 5" 672 | validator={[{ min: 5 }]} 673 | component={[Input]} 674 | decorator={[FormItem]} 675 | /> 676 | 677 | <Field 678 | name="whitespace" 679 | title="Exclude pure whitespace characters" 680 | validator={[{ whitespace: true }]} 681 | component={[Input]} 682 | decorator={[FormItem]} 683 | /> 684 | </Form> 685 | ) 686 | ``` 687 | 688 | ## Built-in Format Verification 689 | 690 | #### Markup Schema Cases 691 | 692 | ```tsx 693 | import React, { Fragment } from 'react' 694 | import { createForm } from '@formily/core' 695 | import { createSchemaField } from '@formily/react' 696 | import { Form, FormItem, Input } from '@formily/antd' 697 | 698 | const form = createForm() 699 | 700 | const SchemaField = createSchemaField({ 701 | components: { 702 | Input, 703 | FormItem, 704 | }, 705 | }) 706 | 707 | const renderFormat = (format: string, key: number) => { 708 | return ( 709 | <Fragment key={key}> 710 | <SchemaField.String 711 | name={`${format}_1`} 712 | title={`${format} format`} 713 | format={format} 714 | required 715 | x-component="Input" 716 | x-decorator="FormItem" 717 | /> 718 | <SchemaField.String 719 | name={`${format}_2`} 720 | title={`${format} format`} 721 | required 722 | x-validator={format} 723 | x-component="Input" 724 | x-decorator="FormItem" 725 | /> 726 | <SchemaField.String 727 | name={`${format}_3`} 728 | title={`${format} format`} 729 | required 730 | x-validator={{ format }} 731 | x-component="Input" 732 | x-decorator="FormItem" 733 | /> 734 | <SchemaField.String 735 | name={`${format}_4`} 736 | title={`${format} format`} 737 | required 738 | x-validator={[format]} 739 | x-component="Input" 740 | x-decorator="FormItem" 741 | /> 742 | <SchemaField.String 743 | name={`${format}_5`} 744 | title={`${format} format`} 745 | required 746 | x-validator={[{ format }]} 747 | x-component="Input" 748 | x-decorator="FormItem" 749 | /> 750 | </Fragment> 751 | ) 752 | } 753 | 754 | const FORMATS = [ 755 | 'url', 756 | 'email', 757 | 'phone', 758 | 'ipv6', 759 | 'ipv4', 760 | 'number', 761 | 'integer', 762 | 'qq', 763 | 'idcard', 764 | 'money', 765 | 'zh', 766 | 'date', 767 | 'zip', 768 | ] 769 | 770 | export default () => ( 771 | <Form form={form} labelCol={6} wrapperCol={10}> 772 | <SchemaField>{FORMATS.map(renderFormat)}</SchemaField> 773 | </Form> 774 | ) 775 | ``` 776 | 777 | #### JSON Schema Cases 778 | 779 | ```tsx 780 | import React from 'react' 781 | import { createForm } from '@formily/core' 782 | import { createSchemaField } from '@formily/react' 783 | import { Form, FormItem, Input } from '@formily/antd' 784 | 785 | const form = createForm() 786 | 787 | const schema = { 788 | type: 'object', 789 | properties: {}, 790 | } 791 | 792 | const FORMATS = [ 793 | 'url', 794 | 'email', 795 | 'phone', 796 | 'ipv6', 797 | 'ipv4', 798 | 'number', 799 | 'integer', 800 | 'qq', 801 | 'idcard', 802 | 'money', 803 | 'zh', 804 | 'date', 805 | 'zip', 806 | ] 807 | 808 | FORMATS.forEach((key) => { 809 | Object.assign(schema.properties, { 810 | [`${key}_1`]: { 811 | title: `${key} format`, 812 | type: 'string', 813 | required: true, 814 | format: key, 815 | 'x-decorator': 'FormItem', 816 | 'x-component': 'Input', 817 | }, 818 | [`${key}_2`]: { 819 | title: `${key} format`, 820 | type: 'string', 821 | required: true, 822 | 'x-validator': key, 823 | 'x-decorator': 'FormItem', 824 | 'x-component': 'Input', 825 | }, 826 | [`${key}_3`]: { 827 | title: `${key} format`, 828 | type: 'string', 829 | required: true, 830 | 'x-validator': { 831 | format: key, 832 | }, 833 | 'x-decorator': 'FormItem', 834 | 'x-component': 'Input', 835 | }, 836 | [`${key}_4`]: { 837 | title: `${key} format`, 838 | type: 'string', 839 | required: true, 840 | 'x-validator': [key], 841 | 'x-decorator': 'FormItem', 842 | 'x-component': 'Input', 843 | }, 844 | 845 | [`${key}_5`]: { 846 | title: `${key} format`, 847 | type: 'string', 848 | required: true, 849 | 'x-validator': [ 850 | { 851 | format: key, 852 | }, 853 | ], 854 | 'x-decorator': 'FormItem', 855 | 'x-component': 'Input', 856 | }, 857 | }) 858 | }) 859 | 860 | const SchemaField = createSchemaField({ 861 | components: { 862 | Input, 863 | FormItem, 864 | }, 865 | }) 866 | 867 | export default () => ( 868 | <Form form={form} labelCol={6} wrapperCol={10}> 869 | <SchemaField schema={schema} /> 870 | </Form> 871 | ) 872 | ``` 873 | 874 | #### Pure JSX Cases 875 | 876 | ```tsx 877 | import React, { Fragment } from 'react' 878 | import { createForm } from '@formily/core' 879 | import { Field } from '@formily/react' 880 | import { Form, FormItem, Input } from '@formily/antd' 881 | 882 | const form = createForm() 883 | 884 | const renderFormat = (format: string, key: number) => { 885 | return ( 886 | <Fragment key={key}> 887 | <Field 888 | name={`${format}_1`} 889 | title={`${format} format`} 890 | required 891 | validator={format} 892 | component={[Input]} 893 | decorator={[FormItem]} 894 | /> 895 | <Field 896 | name={`${format}_2`} 897 | title={`${format} format`} 898 | required 899 | validator={{ format }} 900 | component={[Input]} 901 | decorator={[FormItem]} 902 | /> 903 | <Field 904 | name={`${format}_3`} 905 | title={`${format} format`} 906 | required 907 | validator={[format]} 908 | component={[Input]} 909 | decorator={[FormItem]} 910 | /> 911 | <Field 912 | name={`${format}_4`} 913 | title={`${format} format`} 914 | required 915 | validator={[{ format }]} 916 | component={[Input]} 917 | decorator={[FormItem]} 918 | /> 919 | </Fragment> 920 | ) 921 | } 922 | 923 | const FORMATS = [ 924 | 'url', 925 | 'email', 926 | 'phone', 927 | 'ipv6', 928 | 'ipv4', 929 | 'number', 930 | 'integer', 931 | 'qq', 932 | 'idcard', 933 | 'money', 934 | 'zh', 935 | 'date', 936 | 'zip', 937 | ] 938 | 939 | export default () => ( 940 | <Form form={form} labelCol={6} wrapperCol={10}> 941 | {FORMATS.map(renderFormat)} 942 | </Form> 943 | ) 944 | ``` 945 | 946 | ## Custom Rule Verification 947 | 948 | #### Markup Schema Cases 949 | 950 | ```tsx 951 | import React from 'react' 952 | import { createForm, registerValidateRules } from '@formily/core' 953 | import { createSchemaField } from '@formily/react' 954 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 955 | 956 | const form = createForm() 957 | 958 | const SchemaField = createSchemaField({ 959 | components: { 960 | Input, 961 | FormItem, 962 | NumberPicker, 963 | }, 964 | }) 965 | 966 | registerValidateRules({ 967 | global_1(value) { 968 | if (!value) return '' 969 | return value !== '123' ? 'error❎' : '' 970 | }, 971 | global_2(value, rule) { 972 | if (!value) return '' 973 | return value !== '123' ? rule.message : '' 974 | }, 975 | global_3(value) { 976 | if (!value) return '' 977 | return value === '123' 978 | }, 979 | global_4(value) { 980 | if (!value) return '' 981 | if (value < 10) { 982 | return { 983 | type: 'error', 984 | message: 'The value cannot be less than 10', 985 | } 986 | } else if (value < 100) { 987 | return { 988 | type: 'warning', 989 | message: 'The value is within 100', 990 | } 991 | } else if (value < 1000) { 992 | return { 993 | type: 'success', 994 | message: 'The value is greater than 100 and less than 1000', 995 | } 996 | } 997 | }, 998 | }) 999 | 1000 | export default () => ( 1001 | <Form form={form} labelCol={6} wrapperCol={10}> 1002 | <SchemaField> 1003 | <SchemaField.String 1004 | name="global_style_1" 1005 | title="Global registration style" 1006 | required 1007 | x-validator={{ 1008 | global_1: true, 1009 | }} 1010 | x-component="Input" 1011 | x-decorator="FormItem" 1012 | /> 1013 | <SchemaField.String 1014 | name="global_style_2" 1015 | title="Global registration style" 1016 | required 1017 | x-validator={{ 1018 | global_2: true, 1019 | message: 'error❎', 1020 | }} 1021 | x-component="Input" 1022 | x-decorator="FormItem" 1023 | /> 1024 | <SchemaField.String 1025 | name="global_style_3" 1026 | title="Global registration style" 1027 | required 1028 | x-validator={{ 1029 | global_3: true, 1030 | message: 'error❎', 1031 | }} 1032 | x-component="Input" 1033 | x-decorator="FormItem" 1034 | /> 1035 | <SchemaField.Number 1036 | name="global_style_4" 1037 | title="Global registration style" 1038 | required 1039 | x-validator={{ 1040 | global_4: true, 1041 | }} 1042 | x-component="NumberPicker" 1043 | x-decorator="FormItem" 1044 | /> 1045 | 1046 | <SchemaField.String 1047 | name="validator_style_1" 1048 | title="Locally defined style" 1049 | required 1050 | x-validator={(value) => { 1051 | if (!value) return '' 1052 | return value !== '123' ? 'error❎' : '' 1053 | }} 1054 | x-component="Input" 1055 | x-decorator="FormItem" 1056 | /> 1057 | <SchemaField.String 1058 | name="validator_style_2" 1059 | title="Locally defined style" 1060 | required 1061 | x-validator={{ 1062 | validator(value, rule) { 1063 | if (!value) return '' 1064 | return value !== '123' ? rule.message : '' 1065 | }, 1066 | message: 'error❎', 1067 | }} 1068 | x-component="Input" 1069 | x-decorator="FormItem" 1070 | /> 1071 | <SchemaField.String 1072 | name="validator_style_3" 1073 | title="Locally defined style" 1074 | required 1075 | x-validator={{ 1076 | validator(value) { 1077 | if (!value) return '' 1078 | return value === '123' 1079 | }, 1080 | message: 'error❎', 1081 | }} 1082 | x-component="Input" 1083 | x-decorator="FormItem" 1084 | /> 1085 | <SchemaField.Number 1086 | name="validator_style_4" 1087 | title="Locally defined style" 1088 | required 1089 | x-validator={(value) => { 1090 | if (!value) return '' 1091 | if (value < 10) { 1092 | return { 1093 | type: 'error', 1094 | message: 'The value cannot be less than 10', 1095 | } 1096 | } else if (value < 100) { 1097 | return { 1098 | type: 'warning', 1099 | message: 'The value is within 100', 1100 | } 1101 | } else if (value < 1000) { 1102 | return { 1103 | type: 'success', 1104 | message: 'The value is greater than 100 and less than 1000', 1105 | } 1106 | } 1107 | }} 1108 | x-component="NumberPicker" 1109 | x-decorator="FormItem" 1110 | /> 1111 | </SchemaField> 1112 | </Form> 1113 | ) 1114 | ``` 1115 | 1116 | #### JSON Schema Cases 1117 | 1118 | ```tsx 1119 | import React from 'react' 1120 | import { createForm, registerValidateRules } from '@formily/core' 1121 | import { createSchemaField } from '@formily/react' 1122 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 1123 | 1124 | const form = createForm() 1125 | 1126 | const SchemaField = createSchemaField({ 1127 | components: { 1128 | Input, 1129 | FormItem, 1130 | NumberPicker, 1131 | }, 1132 | }) 1133 | 1134 | registerValidateRules({ 1135 | global_1(value) { 1136 | if (!value) return '' 1137 | return value !== '123' ? 'error❎' : '' 1138 | }, 1139 | global_2(value, rule) { 1140 | if (!value) return '' 1141 | return value !== '123' ? rule.message : '' 1142 | }, 1143 | global_3(value) { 1144 | if (!value) return '' 1145 | return value === '123' 1146 | }, 1147 | global_4(value) { 1148 | if (!value) return '' 1149 | if (value < 10) { 1150 | return { 1151 | type: 'error', 1152 | message: 'The value cannot be less than 10', 1153 | } 1154 | } else if (value < 100) { 1155 | return { 1156 | type: 'warning', 1157 | message: 'The value is within 100', 1158 | } 1159 | } else if (value < 1000) { 1160 | return { 1161 | type: 'success', 1162 | message: 'The value is greater than 100 and less than 1000', 1163 | } 1164 | } 1165 | }, 1166 | }) 1167 | 1168 | const schema = { 1169 | type: 'object', 1170 | properties: { 1171 | global_style_1: { 1172 | title: 'Global registration style', 1173 | required: true, 1174 | 'x-validator': { 1175 | global_1: true, 1176 | }, 1177 | 'x-component': 'Input', 1178 | 'x-decorator': 'FormItem', 1179 | }, 1180 | global_style_2: { 1181 | title: 'Global registration style', 1182 | required: true, 1183 | 'x-validator': { 1184 | global_2: true, 1185 | message: 'error❎', 1186 | }, 1187 | 'x-component': 'Input', 1188 | 'x-decorator': 'FormItem', 1189 | }, 1190 | global_style_3: { 1191 | title: 'Global registration style', 1192 | required: true, 1193 | 'x-validator': { 1194 | global_3: true, 1195 | message: 'error❎', 1196 | }, 1197 | 'x-component': 'Input', 1198 | 'x-decorator': 'FormItem', 1199 | }, 1200 | global_style_4: { 1201 | title: 'Global registration style', 1202 | required: true, 1203 | 'x-validator': { 1204 | global_4: true, 1205 | }, 1206 | 'x-component': 'Input', 1207 | 'x-decorator': 'FormItem', 1208 | }, 1209 | 1210 | validator_style_1: { 1211 | title: 'Locally defined style', 1212 | required: true, 1213 | 'x-validator': `{{(value)=> { 1214 | if (!value) return '' 1215 | return value !== '123' ? 'error❎' : '' 1216 | }}}`, 1217 | 'x-component': 'Input', 1218 | 'x-decorator': 'FormItem', 1219 | }, 1220 | validator_style_2: { 1221 | title: 'Locally defined style', 1222 | required: true, 1223 | 'x-validator': { 1224 | validator: `{{(value, rule)=> { 1225 | if (!value) return '' 1226 | return value !== '123' ? rule.message : '' 1227 | }}}`, 1228 | message: 'error❎', 1229 | }, 1230 | 'x-component': 'Input', 1231 | 'x-decorator': 'FormItem', 1232 | }, 1233 | validator_style_3: { 1234 | title: 'Locally defined style', 1235 | required: true, 1236 | 'x-validator': { 1237 | validator: `{{(value, rule)=> { 1238 | if (!value) return '' 1239 | return value === '123' 1240 | }}}`, 1241 | message: 'error❎', 1242 | }, 1243 | 'x-component': 'Input', 1244 | 'x-decorator': 'FormItem', 1245 | }, 1246 | validator_style_4: { 1247 | title: 'Locally defined style', 1248 | required: true, 1249 | 'x-validator': `{{(value, rule)=> { 1250 | if (!value) return '' 1251 | if (value < 10) { 1252 | return { 1253 | type: 'error', 1254 | message: 'The value cannot be less than 10', 1255 | } 1256 | } else if (value < 100) { 1257 | return { 1258 | type: 'warning', 1259 | message: 'The value is within 100', 1260 | } 1261 | } else if (value < 1000) { 1262 | return { 1263 | type: 'success', 1264 | message: 'The value is greater than 100 and less than 1000', 1265 | } 1266 | } 1267 | }}}`, 1268 | 'x-component': 'Input', 1269 | 'x-decorator': 'FormItem', 1270 | }, 1271 | }, 1272 | } 1273 | 1274 | export default () => ( 1275 | <Form form={form} labelCol={6} wrapperCol={10}> 1276 | <SchemaField schema={schema} /> 1277 | </Form> 1278 | ) 1279 | ``` 1280 | 1281 | #### Pure JSX Cases 1282 | 1283 | ```tsx 1284 | import React from 'react' 1285 | import { createForm, registerValidateRules } from '@formily/core' 1286 | import { Field } from '@formily/react' 1287 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 1288 | 1289 | const form = createForm() 1290 | 1291 | registerValidateRules({ 1292 | global_1(value) { 1293 | if (!value) return '' 1294 | return value !== '123' ? 'error❎' : '' 1295 | }, 1296 | global_2(value, rule) { 1297 | if (!value) return '' 1298 | return value !== '123' ? rule.message : '' 1299 | }, 1300 | global_3(value) { 1301 | if (!value) return '' 1302 | return value === '123' 1303 | }, 1304 | global_4(value) { 1305 | if (!value) return '' 1306 | if (value < 10) { 1307 | return { 1308 | type: 'error', 1309 | message: 'The value cannot be less than 10', 1310 | } 1311 | } else if (value < 100) { 1312 | return { 1313 | type: 'warning', 1314 | message: 'The value is within 100', 1315 | } 1316 | } else if (value < 1000) { 1317 | return { 1318 | type: 'success', 1319 | message: 'The value is greater than 100 and less than 1000', 1320 | } 1321 | } 1322 | }, 1323 | }) 1324 | 1325 | export default () => ( 1326 | <Form form={form} labelCol={6} wrapperCol={10}> 1327 | <Field 1328 | name="global_style_1" 1329 | title="Global registration style" 1330 | required 1331 | validator={{ 1332 | global_1: true, 1333 | }} 1334 | component={[Input]} 1335 | decorator={[FormItem]} 1336 | /> 1337 | <Field 1338 | name="global_style_2" 1339 | title="Global registration style" 1340 | required 1341 | validator={{ 1342 | global_2: true, 1343 | message: 'error❎', 1344 | }} 1345 | component={[Input]} 1346 | decorator={[FormItem]} 1347 | /> 1348 | <Field 1349 | name="global_style_3" 1350 | title="Global registration style" 1351 | required 1352 | validator={{ 1353 | global_3: true, 1354 | message: 'error❎', 1355 | }} 1356 | component={[Input]} 1357 | decorator={[FormItem]} 1358 | /> 1359 | <Field 1360 | name="global_style_4" 1361 | title="Global registration style" 1362 | required 1363 | validator={{ 1364 | global_4: true, 1365 | }} 1366 | component={[NumberPicker]} 1367 | decorator={[FormItem]} 1368 | /> 1369 | 1370 | <Field 1371 | name="validator_style_1" 1372 | title="Locally defined style" 1373 | required 1374 | validator={(value) => { 1375 | if (!value) return '' 1376 | return value !== '123' ? 'error❎' : '' 1377 | }} 1378 | component={[Input]} 1379 | decorator={[FormItem]} 1380 | /> 1381 | <Field 1382 | name="validator_style_2" 1383 | title="Locally defined style" 1384 | required 1385 | validator={{ 1386 | validator(value, rule) { 1387 | if (!value) return '' 1388 | return value !== '123' ? rule.message : '' 1389 | }, 1390 | message: 'error❎', 1391 | }} 1392 | component={[Input]} 1393 | decorator={[FormItem]} 1394 | /> 1395 | <Field 1396 | name="validator_style_3" 1397 | title="Locally defined style" 1398 | required 1399 | validator={{ 1400 | validator(value) { 1401 | if (!value) return '' 1402 | return value === '123' 1403 | }, 1404 | message: 'error❎', 1405 | }} 1406 | component={[Input]} 1407 | decorator={[FormItem]} 1408 | /> 1409 | <Field 1410 | name="validator_style_4" 1411 | title="Locally defined style" 1412 | required 1413 | validator={(value) => { 1414 | if (!value) return '' 1415 | if (value < 10) { 1416 | return { 1417 | type: 'error', 1418 | message: 'The value cannot be less than 10', 1419 | } 1420 | } else if (value < 100) { 1421 | return { 1422 | type: 'warning', 1423 | message: 'The value is within 100', 1424 | } 1425 | } else if (value < 1000) { 1426 | return { 1427 | type: 'success', 1428 | message: 'The value is greater than 100 and less than 1000', 1429 | } 1430 | } 1431 | }} 1432 | component={[NumberPicker]} 1433 | decorator={[FormItem]} 1434 | /> 1435 | </Form> 1436 | ) 1437 | ``` 1438 | 1439 | ## Using Third-Party Validation Libraries 1440 | 1441 | With the powerful validation engine of Formily, it is extremely convenient to adapt to third-party validation libraries such as yup. Here is an example of how to use it: 1442 | 1443 | #### JSON Schema Cases 1444 | 1445 | ```tsx 1446 | import React from 'react' 1447 | import { createForm, registerValidateRules } from '@formily/core' 1448 | import { createSchemaField } from '@formily/react' 1449 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 1450 | import { string } from 'yup' 1451 | 1452 | const form = createForm() 1453 | 1454 | const SchemaField = createSchemaField({ 1455 | components: { 1456 | Input, 1457 | FormItem, 1458 | NumberPicker, 1459 | }, 1460 | }) 1461 | 1462 | registerValidateRules({ 1463 | yup: async (value, rule) => { 1464 | try { 1465 | await rule.yup().validate(value) 1466 | return '' // Return an empty string when validation is successful 1467 | } catch (err) { 1468 | return err.errors.join(',') // Return the error message when validation fails 1469 | } 1470 | }, 1471 | }) 1472 | 1473 | const schema = { 1474 | type: 'object', 1475 | properties: { 1476 | global_style_1: { 1477 | title: 'Maximum length is 2', 1478 | 'x-validator': [ 1479 | { 1480 | triggerType: 'onBlur', 1481 | yup: () => string().required('required'), 1482 | }, 1483 | { 1484 | triggerType: 'onBlur', 1485 | yup: () => string().max(2, 'Maximum length is 2'), 1486 | }, 1487 | ], 1488 | 'x-component': 'Input', 1489 | 'x-decorator': 'FormItem', 1490 | }, 1491 | global_style_2: { 1492 | title: 'email', 1493 | required: true, 1494 | 'x-validator': { 1495 | triggerType: 'onBlur', 1496 | yup: () => string().email(), 1497 | }, 1498 | 'x-component': 'Input', 1499 | 'x-decorator': 'FormItem', 1500 | }, 1501 | }, 1502 | } 1503 | 1504 | export default () => ( 1505 | <Form form={form} labelCol={6} wrapperCol={10}> 1506 | <SchemaField schema={schema} /> 1507 | </Form> 1508 | ) 1509 | ``` 1510 | 1511 | #### Pure JSX Cases 1512 | 1513 | ```tsx 1514 | import React from 'react' 1515 | import { createForm, registerValidateRules } from '@formily/core' 1516 | import { Field } from '@formily/react' 1517 | import { Form, FormItem, Input, NumberPicker } from '@formily/antd' 1518 | import { string, number } from 'yup' 1519 | 1520 | const form = createForm() 1521 | 1522 | registerValidateRules({ 1523 | yup: async (value, rule) => { 1524 | try { 1525 | await rule.yup().validate(value) 1526 | return '' // Return an empty string when validation is successful 1527 | } catch (err) { 1528 | return err.errors.join(',') // Return the error message when validation fails 1529 | } 1530 | }, 1531 | }) 1532 | 1533 | export default () => ( 1534 | <Form form={form} labelCol={6} wrapperCol={10}> 1535 | <Field 1536 | name="global_style_1" 1537 | title="email" 1538 | required 1539 | validator={{ 1540 | yup: () => string().email(), 1541 | }} 1542 | component={[Input]} 1543 | decorator={[FormItem]} 1544 | /> 1545 | <Field 1546 | name="global_style_2" 1547 | title="max 30" 1548 | required 1549 | validator={{ 1550 | yup: () => number().max(30), 1551 | }} 1552 | component={[NumberPicker]} 1553 | decorator={[FormItem]} 1554 | /> 1555 | <Field 1556 | name="global_style_3" 1557 | title="email" 1558 | required 1559 | validator={{ 1560 | yup: () => string().email(), 1561 | }} 1562 | component={[Input]} 1563 | decorator={[FormItem]} 1564 | /> 1565 | </Form> 1566 | ) 1567 | ``` 1568 | 1569 | ## Custom Format Verification 1570 | 1571 | #### Markup Schema Cases 1572 | 1573 | ```tsx 1574 | import React from 'react' 1575 | import { createForm, registerValidateFormats } from '@formily/core' 1576 | import { createSchemaField } from '@formily/react' 1577 | import { Form, FormItem, Input } from '@formily/antd' 1578 | 1579 | const form = createForm() 1580 | 1581 | const SchemaField = createSchemaField({ 1582 | components: { 1583 | Input, 1584 | FormItem, 1585 | }, 1586 | }) 1587 | 1588 | registerValidateFormats({ 1589 | custom_format: /123/, 1590 | }) 1591 | 1592 | export default () => ( 1593 | <Form form={form} labelCol={6} wrapperCol={10}> 1594 | <SchemaField> 1595 | <SchemaField.String 1596 | name="global_style_1" 1597 | title="Global registration style" 1598 | required 1599 | x-validator={{ 1600 | format: 'custom_format', 1601 | message: 'error❎', 1602 | }} 1603 | x-component="Input" 1604 | x-decorator="FormItem" 1605 | /> 1606 | <SchemaField.String 1607 | name="global_style_2" 1608 | title="Global registration style" 1609 | required 1610 | x-validator={'custom_format'} 1611 | x-component="Input" 1612 | x-decorator="FormItem" 1613 | /> 1614 | <SchemaField.String 1615 | name="global_style_3" 1616 | title="Global registration style" 1617 | required 1618 | x-validator={['custom_format']} 1619 | x-component="Input" 1620 | x-decorator="FormItem" 1621 | /> 1622 | <SchemaField.Number 1623 | name="global_style_4" 1624 | title="Global registration style" 1625 | required 1626 | x-validator={{ 1627 | format: 'custom_format', 1628 | message: 'error❎', 1629 | }} 1630 | x-component="Input" 1631 | x-decorator="FormItem" 1632 | /> 1633 | 1634 | <SchemaField.String 1635 | name="validator_style_1" 1636 | title="Locally defined style" 1637 | required 1638 | pattern={/123/} 1639 | x-component="Input" 1640 | x-decorator="FormItem" 1641 | /> 1642 | <SchemaField.String 1643 | name="validator_style_2" 1644 | title="Locally defined style" 1645 | required 1646 | pattern="123" 1647 | x-component="Input" 1648 | x-decorator="FormItem" 1649 | /> 1650 | <SchemaField.String 1651 | name="validator_style_3" 1652 | title="Locally defined style" 1653 | required 1654 | x-validator={{ 1655 | pattern: /123/, 1656 | message: 'error❎', 1657 | }} 1658 | x-component="Input" 1659 | x-decorator="FormItem" 1660 | /> 1661 | <SchemaField.String 1662 | name="validator_style_4" 1663 | title="Locally defined style" 1664 | required 1665 | x-validator={{ 1666 | pattern: '123', 1667 | message: 'error❎', 1668 | }} 1669 | x-component="Input" 1670 | x-decorator="FormItem" 1671 | /> 1672 | </SchemaField> 1673 | </Form> 1674 | ) 1675 | ``` 1676 | 1677 | #### JSON Schema Cases 1678 | 1679 | ```tsx 1680 | import React from 'react' 1681 | import { createForm, registerValidateFormats } from '@formily/core' 1682 | import { createSchemaField } from '@formily/react' 1683 | import { Form, FormItem, Input } from '@formily/antd' 1684 | 1685 | const form = createForm() 1686 | 1687 | const SchemaField = createSchemaField({ 1688 | components: { 1689 | Input, 1690 | FormItem, 1691 | }, 1692 | }) 1693 | 1694 | registerValidateFormats({ 1695 | custom_format: /123/, 1696 | }) 1697 | 1698 | const schema = { 1699 | type: 'object', 1700 | properties: { 1701 | global_style_1: { 1702 | title: 'Global registration style', 1703 | required: true, 1704 | 'x-validator': { 1705 | format: 'custom_format', 1706 | message: 'error❎', 1707 | }, 1708 | 'x-component': 'Input', 1709 | 'x-decorator': 'FormItem', 1710 | }, 1711 | global_style_2: { 1712 | title: 'Global registration style', 1713 | required: true, 1714 | 'x-validator': 'custom_format', 1715 | 'x-component': 'Input', 1716 | 'x-decorator': 'FormItem', 1717 | }, 1718 | global_style_3: { 1719 | title: 'Global registration style', 1720 | required: true, 1721 | 'x-validator': ['custom_format'], 1722 | 'x-component': 'Input', 1723 | 'x-decorator': 'FormItem', 1724 | }, 1725 | global_style_4: { 1726 | title: 'Global registration style', 1727 | required: true, 1728 | 'x-validator': { 1729 | format: 'custom_format', 1730 | message: 'error❎', 1731 | }, 1732 | 'x-component': 'Input', 1733 | 'x-decorator': 'FormItem', 1734 | }, 1735 | validator_style_1: { 1736 | title: 'Locally defined style', 1737 | required: true, 1738 | pattern: /123/, 1739 | 'x-component': 'Input', 1740 | 'x-decorator': 'FormItem', 1741 | }, 1742 | validator_style_2: { 1743 | title: 'Locally defined style', 1744 | required: true, 1745 | pattern: '123', 1746 | 'x-component': 'Input', 1747 | 'x-decorator': 'FormItem', 1748 | }, 1749 | validator_style_3: { 1750 | title: 'Locally defined style', 1751 | required: true, 1752 | 'x-validator': { 1753 | pattern: /123/, 1754 | message: 'error❎', 1755 | }, 1756 | 'x-component': 'Input', 1757 | 'x-decorator': 'FormItem', 1758 | }, 1759 | validator_style_4: { 1760 | title: 'Locally defined style', 1761 | required: true, 1762 | 'x-validator': { 1763 | pattern: '123', 1764 | message: 'error❎', 1765 | }, 1766 | 'x-component': 'Input', 1767 | 'x-decorator': 'FormItem', 1768 | }, 1769 | }, 1770 | } 1771 | 1772 | export default () => ( 1773 | <Form form={form} labelCol={6} wrapperCol={10}> 1774 | <SchemaField schema={schema} /> 1775 | </Form> 1776 | ) 1777 | ``` 1778 | 1779 | #### Pure JSX Cases 1780 | 1781 | ```tsx 1782 | import React from 'react' 1783 | import { createForm, registerValidateFormats } from '@formily/core' 1784 | import { Field } from '@formily/react' 1785 | import { Form, FormItem, Input } from '@formily/antd' 1786 | 1787 | const form = createForm() 1788 | 1789 | registerValidateFormats({ 1790 | custom_format: /123/, 1791 | }) 1792 | 1793 | export default () => ( 1794 | <Form form={form} labelCol={6} wrapperCol={10}> 1795 | <Field 1796 | name="global_style_1" 1797 | title="Global registration style" 1798 | required 1799 | validator={{ 1800 | format: 'custom_format', 1801 | message: 'error❎', 1802 | }} 1803 | component={[Input]} 1804 | decorator={[FormItem]} 1805 | /> 1806 | <Field 1807 | name="global_style_2" 1808 | title="Global registration style" 1809 | required 1810 | validator={'custom_format'} 1811 | component={[Input]} 1812 | decorator={[FormItem]} 1813 | /> 1814 | <Field 1815 | name="global_style_3" 1816 | title="Global registration style" 1817 | required 1818 | validator={['custom_format']} 1819 | component={[Input]} 1820 | decorator={[FormItem]} 1821 | /> 1822 | <Field 1823 | name="global_style_4" 1824 | title="Global registration style" 1825 | required 1826 | validator={{ 1827 | format: 'custom_format', 1828 | message: 'error❎', 1829 | }} 1830 | component={[Input]} 1831 | decorator={[FormItem]} 1832 | /> 1833 | <Field 1834 | name="validator_style_1" 1835 | title="Locally defined style" 1836 | required 1837 | validator={{ 1838 | pattern: /123/, 1839 | message: 'error❎', 1840 | }} 1841 | component={[Input]} 1842 | decorator={[FormItem]} 1843 | /> 1844 | <Field 1845 | name="validator_style_2" 1846 | title="Locally defined style" 1847 | required 1848 | validator={{ 1849 | pattern: '123', 1850 | message: 'error❎', 1851 | }} 1852 | component={[Input]} 1853 | decorator={[FormItem]} 1854 | /> 1855 | </Form> 1856 | ) 1857 | ``` 1858 | 1859 | ## Asynchronous Verification 1860 | 1861 | #### Markup Schema Cases 1862 | 1863 | ```tsx 1864 | import React from 'react' 1865 | import { createForm } from '@formily/core' 1866 | import { createSchemaField } from '@formily/react' 1867 | import { Form, FormItem, Input } from '@formily/antd' 1868 | 1869 | const form = createForm() 1870 | 1871 | const SchemaField = createSchemaField({ 1872 | components: { 1873 | Input, 1874 | FormItem, 1875 | }, 1876 | }) 1877 | 1878 | export default () => ( 1879 | <Form form={form} labelCol={6} wrapperCol={10}> 1880 | <SchemaField> 1881 | <SchemaField.String 1882 | name="async_validate" 1883 | title="Asynchronous verification" 1884 | required 1885 | x-validator={(value) => { 1886 | return new Promise((resolve) => { 1887 | setTimeout(() => { 1888 | if (!value) { 1889 | resolve('') 1890 | } 1891 | if (value === '123') { 1892 | resolve('') 1893 | } else { 1894 | resolve('error❎') 1895 | } 1896 | }, 1000) 1897 | }) 1898 | }} 1899 | x-component="Input" 1900 | x-decorator="FormItem" 1901 | /> 1902 | <SchemaField.String 1903 | name="async_validate_2" 1904 | title="Asynchronous verification (onBlur trigger)" 1905 | required 1906 | x-validator={{ 1907 | triggerType: 'onBlur', 1908 | validator: (value) => { 1909 | return new Promise((resolve) => { 1910 | setTimeout(() => { 1911 | if (!value) { 1912 | resolve('') 1913 | } 1914 | if (value === '123') { 1915 | resolve('') 1916 | } else { 1917 | resolve('error❎') 1918 | } 1919 | }, 1000) 1920 | }) 1921 | }, 1922 | }} 1923 | x-component="Input" 1924 | x-decorator="FormItem" 1925 | /> 1926 | </SchemaField> 1927 | </Form> 1928 | ) 1929 | ``` 1930 | 1931 | #### JSON Schema Cases 1932 | 1933 | ```tsx 1934 | import React from 'react' 1935 | import { createForm } from '@formily/core' 1936 | import { createSchemaField } from '@formily/react' 1937 | import { Form, FormItem, Input } from '@formily/antd' 1938 | 1939 | const form = createForm() 1940 | 1941 | const SchemaField = createSchemaField({ 1942 | components: { 1943 | Input, 1944 | FormItem, 1945 | }, 1946 | }) 1947 | 1948 | const schema = { 1949 | type: 'object', 1950 | properties: { 1951 | async_validate: { 1952 | title: 'Asynchronous verification', 1953 | required: true, 1954 | 'x-validator': `{{(value) => { 1955 | return new Promise((resolve) => { 1956 | setTimeout(() => { 1957 | if (!value) { 1958 | resolve('') 1959 | } 1960 | if (value === '123') { 1961 | resolve('') 1962 | } else { 1963 | resolve('error❎') 1964 | } 1965 | }, 1000) 1966 | }) 1967 | }}}`, 1968 | 'x-component': 'Input', 1969 | 'x-decorator': 'FormItem', 1970 | }, 1971 | async_validate_2: { 1972 | title: 'Asynchronous verification (onBlur trigger)', 1973 | required: true, 1974 | 'x-validator': { 1975 | triggerType: 'onBlur', 1976 | validator: `{{(value) => { 1977 | return new Promise((resolve) => { 1978 | setTimeout(() => { 1979 | if (!value) { 1980 | resolve('') 1981 | } 1982 | if (value === '123') { 1983 | resolve('') 1984 | } else { 1985 | resolve('错误❎') 1986 | } 1987 | }, 1000) 1988 | }) 1989 | }}}`, 1990 | }, 1991 | 'x-component': 'Input', 1992 | 'x-decorator': 'FormItem', 1993 | }, 1994 | }, 1995 | } 1996 | 1997 | export default () => ( 1998 | <Form form={form} labelCol={6} wrapperCol={10}> 1999 | <SchemaField schema={schema} /> 2000 | </Form> 2001 | ) 2002 | ``` 2003 | 2004 | #### Pure JSX Cases 2005 | 2006 | ```tsx 2007 | import React from 'react' 2008 | import { createForm } from '@formily/core' 2009 | import { Field } from '@formily/react' 2010 | import { Form, FormItem, Input } from '@formily/antd' 2011 | 2012 | const form = createForm() 2013 | 2014 | export default () => ( 2015 | <Form form={form} labelCol={6} wrapperCol={10}> 2016 | <Field 2017 | name="async_validate" 2018 | title="Asynchronous verification" 2019 | required 2020 | validator={(value) => { 2021 | return new Promise((resolve) => { 2022 | setTimeout(() => { 2023 | if (!value) { 2024 | resolve('') 2025 | } 2026 | if (value === '123') { 2027 | resolve('') 2028 | } else { 2029 | resolve('error❎') 2030 | } 2031 | }, 1000) 2032 | }) 2033 | }} 2034 | component={[Input]} 2035 | decorator={[FormItem]} 2036 | /> 2037 | <Field 2038 | name="async_validate_2" 2039 | title="Asynchronous verification (onBlur trigger)" 2040 | required 2041 | validator={{ 2042 | triggerType: 'onBlur', 2043 | validator: (value) => { 2044 | return new Promise((resolve) => { 2045 | setTimeout(() => { 2046 | if (!value) { 2047 | resolve('') 2048 | } 2049 | if (value === '123') { 2050 | resolve('') 2051 | } else { 2052 | resolve('error ❎') 2053 | } 2054 | }, 1000) 2055 | }) 2056 | }, 2057 | }} 2058 | component={[Input]} 2059 | decorator={[FormItem]} 2060 | /> 2061 | </Form> 2062 | ) 2063 | ``` 2064 | 2065 | ## Linkage Verification 2066 | 2067 | #### Markup Schema Cases 2068 | 2069 | ```tsx 2070 | import React from 'react' 2071 | import { createForm } from '@formily/core' 2072 | import { createSchemaField } from '@formily/react' 2073 | import { Form, FormItem, NumberPicker } from '@formily/antd' 2074 | 2075 | const form = createForm() 2076 | 2077 | const SchemaField = createSchemaField({ 2078 | components: { 2079 | NumberPicker, 2080 | FormItem, 2081 | }, 2082 | }) 2083 | 2084 | export default () => ( 2085 | <Form form={form} labelCol={6} wrapperCol={10}> 2086 | <SchemaField> 2087 | <SchemaField.String 2088 | name="aa" 2089 | title="AA" 2090 | required 2091 | x-reactions={(field) => { 2092 | field.selfErrors = 2093 | field.query('bb').value() >= field.value 2094 | ? 'AA must be greater than BB' 2095 | : '' 2096 | }} 2097 | x-component="NumberPicker" 2098 | x-decorator="FormItem" 2099 | /> 2100 | <SchemaField.String 2101 | name="bb" 2102 | title="BB" 2103 | required 2104 | x-reactions={(field) => { 2105 | field.selfErrors = 2106 | field.query('aa').value() <= field.value 2107 | ? 'AA must be greater than BB' 2108 | : '' 2109 | }} 2110 | x-component="NumberPicker" 2111 | x-decorator="FormItem" 2112 | /> 2113 | </SchemaField> 2114 | </Form> 2115 | ) 2116 | ``` 2117 | 2118 | #### JSON Schema Cases 2119 | 2120 | ```tsx 2121 | import React from 'react' 2122 | import { createForm } from '@formily/core' 2123 | import { createSchemaField } from '@formily/react' 2124 | import { Form, FormItem, NumberPicker } from '@formily/antd' 2125 | 2126 | const form = createForm() 2127 | 2128 | const SchemaField = createSchemaField({ 2129 | components: { 2130 | NumberPicker, 2131 | FormItem, 2132 | }, 2133 | }) 2134 | 2135 | const schema = { 2136 | type: 'object', 2137 | properties: { 2138 | aa: { 2139 | title: 'AA', 2140 | required: true, 2141 | 'x-reactions': `{{(field) => { 2142 | field.selfErrors = 2143 | field.query('bb').value() >= field.value ? 'AA must be greater than BB' : '' 2144 | }}}`, 2145 | 'x-component': 'NumberPicker', 2146 | 'x-decorator': 'FormItem', 2147 | }, 2148 | bb: { 2149 | title: 'BB', 2150 | required: true, 2151 | 'x-reactions': { 2152 | dependencies: ['aa'], 2153 | fulfill: { 2154 | state: { 2155 | selfErrors: 2156 | "{{$deps[0] <= $self.value ? 'AA must be greater than BB' : ''}}", 2157 | }, 2158 | }, 2159 | }, 2160 | 'x-component': 'NumberPicker', 2161 | 'x-decorator': 'FormItem', 2162 | }, 2163 | }, 2164 | } 2165 | 2166 | export default () => ( 2167 | <Form form={form} labelCol={6} wrapperCol={10}> 2168 | <SchemaField schema={schema} /> 2169 | </Form> 2170 | ) 2171 | ``` 2172 | 2173 | #### Pure JSX Cases 2174 | 2175 | ```tsx 2176 | import React from 'react' 2177 | import { createForm } from '@formily/core' 2178 | import { Field } from '@formily/react' 2179 | import { Form, FormItem, NumberPicker } from '@formily/antd' 2180 | 2181 | const form = createForm() 2182 | 2183 | export default () => ( 2184 | <Form form={form} labelCol={6} wrapperCol={10}> 2185 | <Field 2186 | name="aa" 2187 | title="AA" 2188 | required 2189 | reactions={(field) => { 2190 | field.selfErrors = 2191 | field.query('bb').value() >= field.value 2192 | ? 'AA must be greater than BB' 2193 | : '' 2194 | }} 2195 | component={[NumberPicker]} 2196 | decorator={[FormItem]} 2197 | /> 2198 | <Field 2199 | name="bb" 2200 | title="BB" 2201 | required 2202 | reactions={(field) => { 2203 | field.selfErrors = 2204 | field.query('aa').value() <= field.value 2205 | ? 'AA must be greater than BB' 2206 | : '' 2207 | }} 2208 | component={[NumberPicker]} 2209 | decorator={[FormItem]} 2210 | /> 2211 | </Form> 2212 | ) 2213 | ``` 2214 | 2215 | ## Custom Verification Messages 2216 | 2217 | Mainly through [registerValidateLocale](https://core.formilyjs.org/api/entry/form-validator-registry#registervalidatelocale) to customize the built-in verification messages 2218 | 2219 | ```tsx 2220 | import React from 'react' 2221 | import { 2222 | createForm, 2223 | registerValidateLocale, 2224 | setValidateLanguage, 2225 | } from '@formily/core' 2226 | import { createSchemaField } from '@formily/react' 2227 | import { Form, FormItem, Input } from '@formily/antd' 2228 | 2229 | const form = createForm() 2230 | 2231 | const SchemaField = createSchemaField({ 2232 | components: { 2233 | FormItem, 2234 | Input, 2235 | }, 2236 | }) 2237 | 2238 | setValidateLanguage('en-US') 2239 | 2240 | registerValidateLocale({ 2241 | 'en-US': { 2242 | required: 'Custom required verification message', 2243 | }, 2244 | }) 2245 | 2246 | export default () => ( 2247 | <Form form={form} labelCol={6} wrapperCol={10}> 2248 | <SchemaField> 2249 | <SchemaField.String 2250 | name="aa" 2251 | title="AA" 2252 | required 2253 | x-component="Input" 2254 | x-decorator="FormItem" 2255 | /> 2256 | </SchemaField> 2257 | </Form> 2258 | ) 2259 | ``` 2260 | ```