From 4f0c5b8ce123e2d04a79e85a71fd6c8645aee138 Mon Sep 17 00:00:00 2001
From: tangjinzhou <415800467@qq.com>
Date: Fri, 4 May 2018 12:16:17 +0800
Subject: [PATCH] feat: add vc-form demo
---
components/_util/vnode.js | 3 +-
components/vc-form/demo/async-init.js | 123 ++++++++++++
components/vc-form/demo/dynamic-fields.js | 201 +++++++++++++++++++
components/vc-form/demo/dynamic.js | 131 ++++++++++++
components/vc-form/demo/file-input.js | 83 ++++++++
components/vc-form/demo/getFieldDecorator.js | 55 +++++
components/vc-form/src/createBaseForm.jsx | 77 ++++---
components/vc-form/src/index.jsx | 4 +-
8 files changed, 645 insertions(+), 32 deletions(-)
create mode 100644 components/vc-form/demo/async-init.js
create mode 100644 components/vc-form/demo/dynamic-fields.js
create mode 100644 components/vc-form/demo/dynamic.js
create mode 100644 components/vc-form/demo/file-input.js
create mode 100644 components/vc-form/demo/getFieldDecorator.js
diff --git a/components/_util/vnode.js b/components/_util/vnode.js
index 4f7e91e0c..a7e40ec98 100644
--- a/components/_util/vnode.js
+++ b/components/_util/vnode.js
@@ -60,7 +60,7 @@ export function cloneElement (n, nodeProps, deep) {
return null
}
const node = cloneVNode(ele, deep)
- const { props = {}, key, on = {}, children } = nodeProps
+ const { props = {}, key, on = {}, children, directives = [] } = nodeProps
const data = node.data || {}
let cls = {}
let style = {}
@@ -101,6 +101,7 @@ export function cloneElement (n, nodeProps, deep) {
class: cls,
domProps: { ...data.domProps, ...domProps },
scopedSlots: { ...data.scopedSlots, ...scopedSlots },
+ directives: [...(data.directives || []), ...directives],
})
if (node.componentOptions) {
diff --git a/components/vc-form/demo/async-init.js b/components/vc-form/demo/async-init.js
new file mode 100644
index 000000000..e46039e1f
--- /dev/null
+++ b/components/vc-form/demo/async-init.js
@@ -0,0 +1,123 @@
+/* eslint react/no-multi-comp:0, no-console:0 */
+
+import { createForm } from '../index'
+import { regionStyle, errorStyle } from './styles'
+import BaseMixin from '../../_util/BaseMixin'
+
+const Email = {
+ props: {
+ form: Object,
+ },
+ methods: {
+ checkSpecial (rule, value, callback) {
+ setTimeout(() => {
+ if (value === 'yiminghe@gmail.com') {
+ callback('can not be!')
+ } else {
+ callback()
+ }
+ }, 1000)
+ },
+ },
+
+ render () {
+ const { getFieldProps, getFieldError, isFieldValidating } = this.form
+ const errors = getFieldError('email')
+ return (
+
email validate onBlur
+
+
+
+ {errors ? errors.join(',') : null}
+
+
+ {isFieldValidating('email') ? 'validating' : null}
+
+
)
+ },
+}
+
+const Form = {
+ mixins: [BaseMixin],
+ props: {
+ form: Object,
+ },
+ data () {
+ return {
+ loading: true,
+ }
+ },
+
+ mounted () {
+ setTimeout(() => {
+ this.setState({
+ loading: false,
+ }, () => {
+ setTimeout(() => {
+ this.form.setFieldsInitialValue({
+ email: 'xx@gmail.com',
+ })
+ }, 1000)
+ })
+ }, 1000)
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.submit((callback) => {
+ setTimeout(() => {
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ callback()
+ })
+ }, 1000)
+ })
+ },
+
+ reset (e) {
+ e.preventDefault()
+ this.form.resetFields()
+ },
+ },
+
+ render () {
+ if (this.loading) {
+ return loading
+ }
+ const { form } = this
+ const disabled = form.isFieldsValidating() || form.isSubmitting()
+ return ()
+ },
+}
+
+export default createForm()(Form)
diff --git a/components/vc-form/demo/dynamic-fields.js b/components/vc-form/demo/dynamic-fields.js
new file mode 100644
index 000000000..5bf0fa7e7
--- /dev/null
+++ b/components/vc-form/demo/dynamic-fields.js
@@ -0,0 +1,201 @@
+/* eslint react/no-multi-comp:0, no-console:0 */
+
+import { createForm } from '../index'
+import BaseMixin from '../../_util/BaseMixin'
+
+const Form1 = {
+ mixins: [BaseMixin],
+ props: {
+ form: Object,
+ },
+ data () {
+ return {
+ useInput: true,
+ }
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ })
+ },
+ changeUseInput (e) {
+ this.setState({
+ useInput: e.target.checked,
+ })
+ },
+ },
+
+ render () {
+ const { getFieldError, getFieldDecorator } = this.form
+
+ return (
+
+ )
+ },
+}
+
+const Form2 = {
+ mixins: [BaseMixin],
+ props: {
+ form: Object,
+ },
+ data () {
+ return {
+ useInput: true,
+ }
+ },
+ beforeMount () {
+ const { getFieldDecorator } = this.form
+ this.nameDecorator = getFieldDecorator('name', {
+ initialValue: '',
+ rules: [{
+ required: true,
+ message: 'What\'s your name?',
+ }],
+ })
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ })
+ },
+ changeUseInput (e) {
+ this.setState({
+ useInput: e.target.checked,
+ })
+ },
+ },
+
+ render () {
+ const { getFieldError } = this.form
+ return (
+
+ )
+ },
+}
+
+const Form3 = {
+ mixins: [BaseMixin],
+ props: {
+ form: Object,
+ },
+ data () {
+ return {
+ useInput: false,
+ }
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ })
+ },
+ changeUseInput (e) {
+ this.setState({
+ useInput: e.target.checked,
+ })
+ },
+ },
+
+ render () {
+ const { getFieldError, getFieldDecorator } = this.form
+ return (
+
+ )
+ },
+}
+
+const WrappedForm1 = createForm()(Form1)
+const WrappedForm2 = createForm()(Form2)
+const WrappedForm3 = createForm()(Form3)
+
+export default {
+ render () {
+ return (
+
+
+
+
+
+ )
+ },
+}
diff --git a/components/vc-form/demo/dynamic.js b/components/vc-form/demo/dynamic.js
new file mode 100644
index 000000000..dd56eaaa7
--- /dev/null
+++ b/components/vc-form/demo/dynamic.js
@@ -0,0 +1,131 @@
+/* eslint react/no-multi-comp:0, no-console:0 */
+
+import { createForm } from '../index'
+import { regionStyle, errorStyle } from './styles'
+
+const Email = {
+ props: {
+ form: Object,
+ hidden: Boolean,
+ },
+ render () {
+ const { hidden, form } = this
+ const { getFieldProps, getFieldError, isFieldValidating } = form
+ const errors = getFieldError('email')
+ const style = {
+ ...regionStyle,
+ display: hidden ? 'none' : '',
+ }
+ return (
+
email:
+
+
+ {errors ?
{errors.join(',')}
: null}
+
+ {isFieldValidating('email') ?
validating
: null}
+
)
+ },
+
+}
+
+const User = {
+ props: {
+ form: Object,
+ },
+ render () {
+ const { getFieldProps, getFieldError, isFieldValidating } = this.form
+ const errors = getFieldError('user')
+ return (
+
user:
+
+
+ {errors ?
{errors.join(',')}
: null}
+
+ {isFieldValidating('user') ?
validating
: null}
+
)
+ },
+}
+
+const Form = {
+ props: {
+ form: Object,
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ })
+ },
+ },
+
+ render () {
+ const { form } = this
+ const { getFieldProps, getFieldValue } = form
+ return ()
+ },
+}
+
+export default createForm()(Form)
diff --git a/components/vc-form/demo/file-input.js b/components/vc-form/demo/file-input.js
new file mode 100644
index 000000000..0a723a52e
--- /dev/null
+++ b/components/vc-form/demo/file-input.js
@@ -0,0 +1,83 @@
+/* eslint react/no-multi-comp:0, no-console:0 */
+
+import { createForm } from '../index'
+import { regionStyle, errorStyle } from './styles'
+
+function getFileValueProps (value) {
+ if (value && value.target) {
+ return {
+ value: value.target.value,
+ }
+ }
+ return {
+ value,
+ }
+}
+
+function getValueFromFileEvent ({ target }) {
+ return {
+ target,
+ }
+}
+
+const Form = {
+ props: {
+ form: Object,
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ console.log(error, values)
+ if (!error) {
+ console.log('校验通过')
+ }
+ })
+ },
+ checkSize (rule, value, callback) {
+ if (value && value.target) {
+ const files = value.target.files
+ if (files[0]) {
+ callback(files[0].size > 1000000 ? 'file size must be less than 1M' : undefined)
+ } else {
+ callback()
+ }
+ } else {
+ callback()
+ }
+ },
+ },
+
+ render () {
+ const { getFieldProps, getFieldError } = this.form
+ const errors = getFieldError('attachment')
+ return (
+
attachment:
+
+
+
+
+ {(errors) ? errors.join(',') : null}
+
+
+
)
+ },
+}
+
+const NewForm = createForm()(Form)
+
+export default {
+ render () {
+ return (
+
input[type="file"]
+
+ )
+ },
+}
diff --git a/components/vc-form/demo/getFieldDecorator.js b/components/vc-form/demo/getFieldDecorator.js
new file mode 100644
index 000000000..76285870f
--- /dev/null
+++ b/components/vc-form/demo/getFieldDecorator.js
@@ -0,0 +1,55 @@
+/* eslint react/no-multi-comp:0, no-console:0 */
+
+import { createForm } from '../index'
+
+const Form = {
+ props: {
+ form: Object,
+ },
+
+ beforeMount () {
+ this.nameDecorator = this.form.getFieldDecorator('name', {
+ initialValue: '',
+ rules: [{
+ required: true,
+ message: 'What\'s your name?',
+ }],
+ })
+ },
+ methods: {
+ onSubmit (e) {
+ e.preventDefault()
+ this.form.validateFields((error, values) => {
+ if (!error) {
+ console.log('ok', values)
+ } else {
+ console.log('error', error, values)
+ }
+ })
+ },
+
+ onChange (e) {
+ console.log(e.target.value)
+ },
+ },
+
+ render () {
+ const { getFieldError } = this.form
+
+ return (
+
+ )
+ },
+}
+
+export default createForm()(Form)
diff --git a/components/vc-form/src/createBaseForm.jsx b/components/vc-form/src/createBaseForm.jsx
index 4384cb712..07a85baf7 100644
--- a/components/vc-form/src/createBaseForm.jsx
+++ b/components/vc-form/src/createBaseForm.jsx
@@ -5,7 +5,9 @@ import set from 'lodash/set'
import createFieldsStore from './createFieldsStore'
import { cloneElement } from '../../_util/vnode'
import BaseMixin from '../../_util/BaseMixin'
-import PropTypes from '../../_util/vue-types'
+import { getOptionProps, getEvents } from '../../_util/props-util'
+// import PropTypes from '../../_util/vue-types'
+
import {
argumentContainer,
identity,
@@ -18,7 +20,7 @@ import {
flattenArray,
} from './utils'
-const DEFAULT_TRIGGER = 'change'
+const DEFAULT_TRIGGER = 'input'
function createBaseForm (option = {}, mixins = []) {
const {
@@ -38,10 +40,10 @@ function createBaseForm (option = {}, mixins = []) {
return function decorate (WrappedComponent) {
const Form = {
mixins: [BaseMixin, ...mixins],
- props: {
- hideRequiredMark: PropTypes.bool,
- layout: PropTypes.string,
- },
+ // props: {
+ // hideRequiredMark: PropTypes.bool,
+ // layout: PropTypes.string,
+ // },
data () {
const fields = mapPropsToFields && mapPropsToFields(this.$props)
this.fieldsStore = createFieldsStore(fields || {})
@@ -148,10 +150,11 @@ function createBaseForm (option = {}, mixins = []) {
},
getFieldDecorator (name, fieldOption) {
- const { directives, props } = this.getFieldProps(name, fieldOption)
+ const { props, ...restProps } = this.getFieldProps(name, fieldOption)
return (fieldElem) => {
const fieldMeta = this.fieldsStore.getFieldMeta(name)
- const originalProps = fieldElem.props
+ const originalProps = getOptionProps(fieldElem)
+ const originalEvents = getEvents(fieldElem)
if (process.env.NODE_ENV !== 'production') {
const valuePropName = fieldMeta.valuePropName
warning(
@@ -170,14 +173,26 @@ function createBaseForm (option = {}, mixins = []) {
)
}
fieldMeta.originalProps = originalProps
- fieldMeta.ref = fieldElem.ref
- return cloneElement(fieldElem, {
+ // fieldMeta.ref = fieldElem.data && fieldElem.data.ref
+ const newProps = {
props: {
...props,
...this.fieldsStore.getFieldValuePropValue(fieldMeta),
},
- directives,
+ ...restProps,
+ }
+ newProps.domProps.value = newProps.props.value
+ const newEvents = {}
+ Object.keys(newProps.on).forEach((key) => {
+ if (originalEvents[key]) {
+ const triggerEvents = newProps.on[key]
+ newEvents[key] = (...args) => {
+ originalEvents[key](...args)
+ triggerEvents(...args)
+ }
+ }
})
+ return cloneElement(fieldElem, { ...newProps, on: newEvents })
}
},
@@ -221,9 +236,8 @@ function createBaseForm (option = {}, mixins = []) {
const inputProps = {
...this.fieldsStore.getFieldValuePropValue(fieldOption),
// ref: name,
- on: {},
}
- const saveRef = this.getCacheBind(name, `${name}__ref`, this.saveRef)
+ const inputListeners = {}
if (fieldNameProp) {
inputProps[fieldNameProp] = name
}
@@ -231,13 +245,13 @@ function createBaseForm (option = {}, mixins = []) {
const validateRules = normalizeValidateRules(validate, rules, validateTrigger)
const validateTriggers = getValidateTriggers(validateRules)
validateTriggers.forEach((action) => {
- if (inputProps[action]) return
- inputProps[action] = this.getCacheBind(name, action, this.onCollectValidate)
+ if (inputListeners[action]) return
+ inputListeners[action] = this.getCacheBind(name, action, this.onCollectValidate)
})
// make sure that the value will be collect
if (trigger && validateTriggers.indexOf(trigger) === -1) {
- inputProps.on[trigger] = this.getCacheBind(name, trigger, this.onCollect)
+ inputListeners[trigger] = this.getCacheBind(name, trigger, this.onCollect)
}
const meta = {
@@ -256,11 +270,16 @@ function createBaseForm (option = {}, mixins = []) {
return {
props: inputProps,
+ domProps: {
+ value: inputProps.value,
+ },
directives: [
- { name: 'ant-form-item-ref-cal', value: (component) => {
- saveRef(component)
- } },
+ {
+ name: 'ant-ref',
+ value: this.getCacheBind(name, `${name}__ref`, this.saveRef),
+ },
],
+ on: inputListeners,
}
},
@@ -342,16 +361,16 @@ function createBaseForm (option = {}, mixins = []) {
return
}
this.recoverClearedField(name)
- const fieldMeta = this.fieldsStore.getFieldMeta(name)
- if (fieldMeta) {
- const ref = fieldMeta.ref
- if (ref) {
- if (typeof ref === 'string') {
- throw new Error(`can not set ref string for ${name}`)
- }
- ref(component)
- }
- }
+ // const fieldMeta = this.fieldsStore.getFieldMeta(name)
+ // if (fieldMeta) {
+ // const ref = fieldMeta.ref
+ // if (ref) {
+ // if (typeof ref === 'string') {
+ // throw new Error(`can not set ref string for ${name}`)
+ // }
+ // ref(component)
+ // }
+ // }
this.instances[name] = component
},
diff --git a/components/vc-form/src/index.jsx b/components/vc-form/src/index.jsx
index d54a498b7..4d3bdf6d8 100644
--- a/components/vc-form/src/index.jsx
+++ b/components/vc-form/src/index.jsx
@@ -4,8 +4,8 @@ import createFormField from './createFormField'
import formShape from './propTypes'
import Vue from 'vue'
-Vue.directive('ant-form-item-ref-cal', {
- inserted: function (el, binding, vnode) {
+Vue.directive('ant-ref', {
+ bind: function (el, binding, vnode) {
binding.value(vnode)
},
unbind: function (el, binding, vnode) {