Merge remote-tracking branch 'origin/master' into feat-1.4.0
# Conflicts: # components/vc-form/src/createBaseForm.jsxpull/1225/head 1.4.0-beta.0
commit
a3ab0c26f2
|
@ -65,6 +65,7 @@ export const FormProps = {
|
||||||
hideRequiredMark: PropTypes.bool,
|
hideRequiredMark: PropTypes.bool,
|
||||||
autoFormCreate: PropTypes.func,
|
autoFormCreate: PropTypes.func,
|
||||||
options: PropTypes.object,
|
options: PropTypes.object,
|
||||||
|
selfUpdate: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ValidationRule = {
|
export const ValidationRule = {
|
||||||
|
|
|
@ -38,6 +38,7 @@ export const FormItemProps = {
|
||||||
colon: PropTypes.bool,
|
colon: PropTypes.bool,
|
||||||
fieldDecoratorId: PropTypes.string,
|
fieldDecoratorId: PropTypes.string,
|
||||||
fieldDecoratorOptions: PropTypes.object,
|
fieldDecoratorOptions: PropTypes.object,
|
||||||
|
selfUpdate: PropTypes.bool,
|
||||||
};
|
};
|
||||||
function comeFromSlot(vnodes = [], itemVnode) {
|
function comeFromSlot(vnodes = [], itemVnode) {
|
||||||
let isSlot = false;
|
let isSlot = false;
|
||||||
|
@ -73,6 +74,11 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return { helpShow: false };
|
return { helpShow: false };
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
itemSelfUpdate() {
|
||||||
|
return !!(this.selfUpdate === undefined ? this.FormProps.selfUpdate : this.selfUpdate);
|
||||||
|
},
|
||||||
|
},
|
||||||
created() {
|
created() {
|
||||||
this.collectContext();
|
this.collectContext();
|
||||||
},
|
},
|
||||||
|
@ -463,7 +469,7 @@ export default {
|
||||||
}
|
}
|
||||||
const option = this.decoratorOption(vnode);
|
const option = this.decoratorOption(vnode);
|
||||||
if (option && option[0]) {
|
if (option && option[0]) {
|
||||||
vnodes[i] = getFieldDecorator(option[0], option[1])(vnode);
|
vnodes[i] = getFieldDecorator(option[0], option[1], this)(vnode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return vnodes;
|
return vnodes;
|
||||||
|
@ -481,7 +487,7 @@ export default {
|
||||||
let child = filterEmpty($slots.default || []);
|
let child = filterEmpty($slots.default || []);
|
||||||
if (decoratorFormProps.form && fieldDecoratorId && child.length) {
|
if (decoratorFormProps.form && fieldDecoratorId && child.length) {
|
||||||
const getFieldDecorator = decoratorFormProps.form.getFieldDecorator;
|
const getFieldDecorator = decoratorFormProps.form.getFieldDecorator;
|
||||||
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions)(child[0]);
|
child[0] = getFieldDecorator(fieldDecoratorId, fieldDecoratorOptions, this)(child[0]);
|
||||||
warning(
|
warning(
|
||||||
!(child.length > 1),
|
!(child.length > 1),
|
||||||
'`autoFormCreate` just `decorator` then first children. but you can use JSX to support multiple children',
|
'`autoFormCreate` just `decorator` then first children. but you can use JSX to support multiple children',
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
| form | 经 `Form.create()` 包装过的组件会自带 `this.form` 属性,如果使用template语法,可以使用this.$form.createForm(this, options) | object | 无 |
|
| form | 经 `Form.create()` 包装过的组件会自带 `this.form` 属性,如果使用template语法,可以使用this.$form.createForm(this, options) | object | 无 |
|
||||||
| hideRequiredMark | 隐藏所有表单项的必选标记 | Boolean | false |
|
| hideRequiredMark | 隐藏所有表单项的必选标记 | Boolean | false |
|
||||||
| layout | 表单布局 | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
|
| layout | 表单布局 | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
|
||||||
|
| selfUpdate | 自定义字段更新逻辑,说明[见下](/components/form-cn/#selfUpdate),需1.3.17版本以上 | boolean | false |
|
||||||
|
|
||||||
### 事件
|
### 事件
|
||||||
| 事件名称 | 说明 | 回调参数 |
|
| 事件名称 | 说明 | 回调参数 |
|
||||||
|
@ -175,6 +176,7 @@ validateFields(['field1', 'field2'], options, (errors, values) => {
|
||||||
| required | 是否必填,如不设置,则会根据校验规则自动生成 | boolean | false |
|
| required | 是否必填,如不设置,则会根据校验规则自动生成 | boolean | false |
|
||||||
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' | string | |
|
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' | string | |
|
||||||
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid-cn/#Col) | |
|
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | [object](/components/grid-cn/#Col) | |
|
||||||
|
| selfUpdate | 自定义字段更新逻辑,你可以通过 Form 的 selfUpdate 进行统一设置。当和 Form 同时设置时,以 Item 为准。 说明[见下](/components/form-cn/#selfUpdate) 需1.3.17版本以上 | boolean | false |
|
||||||
|
|
||||||
### 校验规则
|
### 校验规则
|
||||||
|
|
||||||
|
@ -195,3 +197,9 @@ validateFields(['field1', 'field2'], options, (errors, values) => {
|
||||||
更多高级用法可研究 [async-validator](https://github.com/yiminghe/async-validator)。
|
更多高级用法可研究 [async-validator](https://github.com/yiminghe/async-validator)。
|
||||||
|
|
||||||
|
|
||||||
|
### selfUpdate
|
||||||
|
|
||||||
|
设置 `selfUpdate` 为 `true` 后,`Form` 通过增量方式更新,只更新被修改的字段。大部分场景下,你只需要编写代码即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都需要进行渲染。你可以通过修改 Form.Item 取消 selfUpdate,或者在 `change` / `onValuesChange` 回调中手动调用 `this.$forceUpdate()` 更新组件。[示例]()
|
||||||
|
|
||||||
|
如果你并不精通 Vue,并不建议使用 selfUpdate,如果出现性能问题,可以尝试这把 Form 相关的业务独立到一个单独的组件中,减少组件渲染的消耗。
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{key: string, label: vNodes}` | boolean | false |
|
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{key: string, label: vNodes}` | boolean | false |
|
||||||
| maxTagCount | Max tag count to show | number | - |
|
| maxTagCount | Max tag count to show | number | - |
|
||||||
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
|
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
|
||||||
|
| maxTagTextLength | Max text length to show | number | - |
|
||||||
| mode | Set mode of Select | 'default' \| 'multiple' \| 'tags' | 'default' |
|
| mode | Set mode of Select | 'default' \| 'multiple' \| 'tags' | 'default' |
|
||||||
| notFoundContent | Specify content to show when no result matches.. | string\|slot | 'Not Found' |
|
| notFoundContent | Specify content to show when no result matches.. | string\|slot | 'Not Found' |
|
||||||
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value |
|
| optionFilterProp | Which prop value of option will be used for filter if filterOption is true | string | value |
|
||||||
|
|
|
@ -63,6 +63,7 @@ const SelectProps = {
|
||||||
firstActiveValue: PropTypes.oneOfType([String, PropTypes.arrayOf(String)]),
|
firstActiveValue: PropTypes.oneOfType([String, PropTypes.arrayOf(String)]),
|
||||||
maxTagCount: PropTypes.number,
|
maxTagCount: PropTypes.number,
|
||||||
maxTagPlaceholder: PropTypes.any,
|
maxTagPlaceholder: PropTypes.any,
|
||||||
|
maxTagTextLength: PropTypes.number,
|
||||||
dropdownMatchSelectWidth: PropTypes.bool,
|
dropdownMatchSelectWidth: PropTypes.bool,
|
||||||
optionFilterProp: PropTypes.string,
|
optionFilterProp: PropTypes.string,
|
||||||
labelInValue: PropTypes.boolean,
|
labelInValue: PropTypes.boolean,
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 `{key: string, label: vNodes}` 的格式 | boolean | false |
|
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 Select 的 value 类型从 `string` 变为 `{key: string, label: vNodes}` 的格式 | boolean | false |
|
||||||
| maxTagCount | 最多显示多少个 tag | number | - |
|
| maxTagCount | 最多显示多少个 tag | number | - |
|
||||||
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
|
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
|
||||||
|
| maxTagTextLength | 最大显示的 tag 文本长度 | number | - |
|
||||||
| mode | 设置 Select 的模式为多选或标签 | 'default' \| 'multiple' \| 'tags' \| 'combobox' | - |
|
| mode | 设置 Select 的模式为多选或标签 | 'default' \| 'multiple' \| 'tags' \| 'combobox' | - |
|
||||||
| notFoundContent | 当下拉列表为空时显示的内容 | string\|slot | 'Not Found' |
|
| notFoundContent | 当下拉列表为空时显示的内容 | string\|slot | 'Not Found' |
|
||||||
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索 | string | value |
|
| optionFilterProp | 搜索时过滤对应的 option 属性,如设置为 children 表示对内嵌内容进行搜索 | string | value |
|
||||||
|
|
|
@ -19,7 +19,7 @@ const Switch = {
|
||||||
disabled: PropTypes.bool,
|
disabled: PropTypes.bool,
|
||||||
checkedChildren: PropTypes.any,
|
checkedChildren: PropTypes.any,
|
||||||
unCheckedChildren: PropTypes.any,
|
unCheckedChildren: PropTypes.any,
|
||||||
tabIndex: PropTypes.number,
|
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
checked: PropTypes.bool,
|
checked: PropTypes.bool,
|
||||||
defaultChecked: PropTypes.bool,
|
defaultChecked: PropTypes.bool,
|
||||||
autoFocus: PropTypes.bool,
|
autoFocus: PropTypes.bool,
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
| getPopupContainer | To set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. | Function(triggerNode) | () => document.body |
|
| getPopupContainer | To set the container of the dropdown menu. The default is to create a `div` element in `body`, you can reset it to the scrolling area and make a relative reposition. | Function(triggerNode) | () => document.body |
|
||||||
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{value: string, label: VNode, halfChecked: string[]}` | boolean | false |
|
| labelInValue | whether to embed label in value, turn the format of value from `string` to `{value: string, label: VNode, halfChecked: string[]}` | boolean | false |
|
||||||
| loadData | Load data asynchronously. | function(node) | - |
|
| loadData | Load data asynchronously. | function(node) | - |
|
||||||
|
| maxTagCount | Max tag count to show | number | - |
|
||||||
|
| maxTagPlaceholder | Placeholder for not showing tags | slot/function(omittedValues) | - |
|
||||||
| multiple | Support multiple or not, will be `true` when enable `treeCheckable`. | boolean | false |
|
| multiple | Support multiple or not, will be `true` when enable `treeCheckable`. | boolean | false |
|
||||||
| placeholder | Placeholder of the select input | string\|slot | - |
|
| placeholder | Placeholder of the select input | string\|slot | - |
|
||||||
| searchPlaceholder | Placeholder of the search input | string\|slot | - |
|
| searchPlaceholder | Placeholder of the search input | string\|slot | - |
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | () => document.body |
|
| getPopupContainer | 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 | Function(triggerNode) | () => document.body |
|
||||||
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 value 类型从 `string` 变为 `{value: string, label: VNode, halfChecked(treeCheckStrictly 时有效): string[] }` 的格式 | boolean | false |
|
| labelInValue | 是否把每个选项的 label 包装到 value 中,会把 value 类型从 `string` 变为 `{value: string, label: VNode, halfChecked(treeCheckStrictly 时有效): string[] }` 的格式 | boolean | false |
|
||||||
| loadData | 异步加载数据 | function(node) | - |
|
| loadData | 异步加载数据 | function(node) | - |
|
||||||
|
| maxTagCount | 最多显示多少个 tag | number | - |
|
||||||
|
| maxTagPlaceholder | 隐藏 tag 时显示的内容 | slot/function(omittedValues) | - |
|
||||||
| multiple | 支持多选(当设置 treeCheckable 时自动变为true) | boolean | false |
|
| multiple | 支持多选(当设置 treeCheckable 时自动变为true) | boolean | false |
|
||||||
| placeholder | 选择框默认文字 | string\|slot | - |
|
| placeholder | 选择框默认文字 | string\|slot | - |
|
||||||
| searchPlaceholder | 搜索框默认文字 | string\|slot | - |
|
| searchPlaceholder | 搜索框默认文字 | string\|slot | - |
|
||||||
|
|
|
@ -61,7 +61,7 @@ function createBaseForm(option = {}, mixins = []) {
|
||||||
this.instances = {};
|
this.instances = {};
|
||||||
this.cachedBind = {};
|
this.cachedBind = {};
|
||||||
this.clearedFieldMetaCache = {};
|
this.clearedFieldMetaCache = {};
|
||||||
|
this.formItems = {};
|
||||||
this.renderFields = {};
|
this.renderFields = {};
|
||||||
this.domFields = {};
|
this.domFields = {};
|
||||||
|
|
||||||
|
@ -182,8 +182,9 @@ function createBaseForm(option = {}, mixins = []) {
|
||||||
return cache[action].fn;
|
return cache[action].fn;
|
||||||
},
|
},
|
||||||
|
|
||||||
getFieldDecorator(name, fieldOption) {
|
getFieldDecorator(name, fieldOption, formItem) {
|
||||||
const { props, ...restProps } = this.getFieldProps(name, fieldOption);
|
const { props, ...restProps } = this.getFieldProps(name, fieldOption);
|
||||||
|
this.formItems[name] = formItem;
|
||||||
return fieldElem => {
|
return fieldElem => {
|
||||||
// We should put field in record if it is rendered
|
// We should put field in record if it is rendered
|
||||||
this.renderFields[name] = true;
|
this.renderFields[name] = true;
|
||||||
|
@ -351,24 +352,30 @@ function createBaseForm(option = {}, mixins = []) {
|
||||||
setFields(maybeNestedFields, callback) {
|
setFields(maybeNestedFields, callback) {
|
||||||
const fields = this.fieldsStore.flattenRegisteredFields(maybeNestedFields);
|
const fields = this.fieldsStore.flattenRegisteredFields(maybeNestedFields);
|
||||||
this.fieldsStore.setFields(fields);
|
this.fieldsStore.setFields(fields);
|
||||||
|
const changedFields = Object.keys(fields).reduce(
|
||||||
|
(acc, name) => set(acc, name, this.fieldsStore.getField(name)),
|
||||||
|
{},
|
||||||
|
);
|
||||||
if (onFieldsChange) {
|
if (onFieldsChange) {
|
||||||
const changedFields = Object.keys(fields).reduce(
|
const changedFields = Object.keys(fields).reduce(
|
||||||
(acc, name) => set(acc, name, this.fieldsStore.getField(name)),
|
(acc, name) => set(acc, name, this.fieldsStore.getField(name)),
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
onFieldsChange(
|
onFieldsChange(this, changedFields, this.fieldsStore.getNestedAllFields());
|
||||||
{
|
|
||||||
[formPropName]: this.getForm(),
|
|
||||||
...this.$props,
|
|
||||||
},
|
|
||||||
changedFields,
|
|
||||||
this.fieldsStore.getNestedAllFields(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if (templateContext) {
|
const formContext = templateContext || this;
|
||||||
templateContext.$forceUpdate();
|
let allUpdate = false;
|
||||||
|
Object.keys(changedFields).forEach(key => {
|
||||||
|
let formItem = this.formItems[key];
|
||||||
|
formItem = typeof formItem === 'function' ? formItem() : formItem;
|
||||||
|
if (formItem && formItem.itemSelfUpdate) {
|
||||||
|
formItem.$forceUpdate();
|
||||||
} else {
|
} else {
|
||||||
this.$forceUpdate();
|
allUpdate = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (allUpdate) {
|
||||||
|
formContext.$forceUpdate();
|
||||||
}
|
}
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
callback && callback();
|
callback && callback();
|
||||||
|
|
|
@ -347,7 +347,11 @@ const Select = {
|
||||||
if (open && !this.getInputDOMNode()) {
|
if (open && !this.getInputDOMNode()) {
|
||||||
this.onInputKeydown(event);
|
this.onInputKeydown(event);
|
||||||
} else if (keyCode === KeyCode.ENTER || keyCode === KeyCode.DOWN) {
|
} else if (keyCode === KeyCode.ENTER || keyCode === KeyCode.DOWN) {
|
||||||
if (!open) {
|
// vue state是同步更新,onKeyDown在onMenuSelect后会再次调用,单选时不在调用setOpenState
|
||||||
|
// https://github.com/vueComponent/ant-design-vue/issues/1142
|
||||||
|
if (keyCode === KeyCode.ENTER && !isMultipleOrTags(this.$props)) {
|
||||||
|
this.maybeFocus(true);
|
||||||
|
} else if (!open) {
|
||||||
this.setOpenState(true);
|
this.setOpenState(true);
|
||||||
}
|
}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
|
@ -8,7 +8,7 @@ export const switchPropTypes = {
|
||||||
// onChange: PropTypes.func,
|
// onChange: PropTypes.func,
|
||||||
// onMouseUp: PropTypes.func,
|
// onMouseUp: PropTypes.func,
|
||||||
// onClick: PropTypes.func,
|
// onClick: PropTypes.func,
|
||||||
tabIndex: PropTypes.number,
|
tabIndex: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
checked: PropTypes.bool.def(false),
|
checked: PropTypes.bool.def(false),
|
||||||
defaultChecked: PropTypes.bool.def(false),
|
defaultChecked: PropTypes.bool.def(false),
|
||||||
autoFocus: PropTypes.bool.def(false),
|
autoFocus: PropTypes.bool.def(false),
|
||||||
|
|
|
@ -79,7 +79,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
render() {
|
render() {
|
||||||
const { prefixCls, disabled, loadingIcon, ...restProps } = getOptionProps(this);
|
const { prefixCls, disabled, loadingIcon, tabIndex, ...restProps } = getOptionProps(this);
|
||||||
const checked = this.stateChecked;
|
const checked = this.stateChecked;
|
||||||
const switchClassName = {
|
const switchClassName = {
|
||||||
[prefixCls]: true,
|
[prefixCls]: true,
|
||||||
|
@ -99,6 +99,7 @@ export default {
|
||||||
role: 'switch',
|
role: 'switch',
|
||||||
'aria-checked': checked,
|
'aria-checked': checked,
|
||||||
disabled,
|
disabled,
|
||||||
|
tabIndex,
|
||||||
},
|
},
|
||||||
class: switchClassName,
|
class: switchClassName,
|
||||||
ref: 'refSwitchNode',
|
ref: 'refSwitchNode',
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ant-design-vue",
|
"name": "ant-design-vue",
|
||||||
"version": "1.3.16",
|
"version": "1.3.17-beta.1",
|
||||||
"title": "Ant Design Vue",
|
"title": "Ant Design Vue",
|
||||||
"description": "An enterprise-class UI design language and Vue-based implementation",
|
"description": "An enterprise-class UI design language and Vue-based implementation",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
|
|
|
@ -12,7 +12,7 @@ import Api from './components/api';
|
||||||
import './components';
|
import './components';
|
||||||
import demoBox from './components/demoBox';
|
import demoBox from './components/demoBox';
|
||||||
import demoContainer from './components/demoContainer';
|
import demoContainer from './components/demoContainer';
|
||||||
import Test from '../components/test/index.vue';
|
import Test from '../components/table/demo/index.vue';
|
||||||
import zhCN from './theme/zh-CN';
|
import zhCN from './theme/zh-CN';
|
||||||
import enUS from './theme/en-US';
|
import enUS from './theme/en-US';
|
||||||
Vue.use(Vuex);
|
Vue.use(Vuex);
|
||||||
|
|
|
@ -118,6 +118,12 @@ export declare class Select extends AntdComponent {
|
||||||
*/
|
*/
|
||||||
maxTagPlaceholder: any;
|
maxTagPlaceholder: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max text length to show
|
||||||
|
* @type number
|
||||||
|
*/
|
||||||
|
maxTagTextLength: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set mode of Select
|
* Set mode of Select
|
||||||
* @default 'default'
|
* @default 'default'
|
||||||
|
|
|
@ -89,6 +89,10 @@ export declare class TreeSelect extends AntdComponent {
|
||||||
*/
|
*/
|
||||||
loadData: (node: any) => void;
|
loadData: (node: any) => void;
|
||||||
|
|
||||||
|
maxTagCount: number;
|
||||||
|
|
||||||
|
maxTagPlaceholder: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Support multiple or not, will be true when enable treeCheckable.
|
* Support multiple or not, will be true when enable treeCheckable.
|
||||||
* @default false
|
* @default false
|
||||||
|
|
Loading…
Reference in New Issue