Merge remote-tracking branch 'origin/next' into refactor-tree

pull/4577/head
tangjinzhou 2021-08-25 10:10:17 +08:00
commit eff286d0e5
10 changed files with 78 additions and 39 deletions

View File

@ -33,7 +33,7 @@ const AutoComplete = defineComponent({
inheritAttrs: false,
props: {
...autoCompleteProps,
prefixCls: PropTypes.string.def('ant-select'),
prefixCls: PropTypes.string,
showSearch: PropTypes.looseBool,
transitionName: PropTypes.string.def('slide-up'),
choiceTransitionName: PropTypes.string.def('zoom'),

View File

@ -318,14 +318,16 @@ const Form = defineComponent({
e.preventDefault();
e.stopPropagation();
emit('submit', e);
const res = validateFields();
res
.then(values => {
emit('finish', values);
})
.catch(errors => {
handleFinishFailed(errors);
});
if (props.model) {
const res = validateFields();
res
.then(values => {
emit('finish', values);
})
.catch(errors => {
handleFinishFailed(errors);
});
}
};
expose({

View File

@ -107,6 +107,8 @@ function useForm(
validateInfos: validateInfos;
resetFields: (newValues?: Props) => void;
validate: <T = any>(names?: namesType, option?: validateOptions) => Promise<T>;
/** This is an internal usage. Do not use in your prod */
validateField: (
name: string,
value: any,
@ -117,19 +119,33 @@ function useForm(
clearValidate: (names?: namesType) => void;
} {
const initialModel = cloneDeep(unref(modelRef));
let validateInfos: validateInfos = {};
const validateInfos = reactive<validateInfos>({});
const rulesKeys = computed(() => {
return Object.keys(unref(rulesRef));
});
rulesKeys.value.forEach(key => {
validateInfos[key] = {
autoLink: false,
required: isRequired(unref(rulesRef)[key]),
};
});
validateInfos = reactive(validateInfos);
watch(
rulesKeys,
() => {
const newValidateInfos = {};
rulesKeys.value.forEach(key => {
newValidateInfos[key] = validateInfos[key] || {
autoLink: false,
required: isRequired(unref(rulesRef)[key]),
};
delete validateInfos[key];
});
for (const key in validateInfos) {
if (Object.prototype.hasOwnProperty.call(validateInfos, key)) {
delete validateInfos[key];
}
}
Object.assign(validateInfos, newValidateInfos);
},
{ immediate: true },
);
const resetFields = (newValues: Props) => {
Object.assign(unref(modelRef), {
...cloneDeep(initialModel),
@ -249,6 +265,9 @@ function useForm(
},
!!option.validateFirst,
);
if (!validateInfos[name]) {
return promise.catch((e: any) => e);
}
validateInfos[name].validateStatus = 'validating';
promise
.catch((e: any) => e)
@ -325,7 +344,9 @@ function useForm(
validate(names, { trigger: 'change' });
oldModel = cloneDeep(model);
};
const debounceOptions = options?.debounce;
watch(
modelRef,
debounceOptions && debounceOptions.wait

View File

@ -1,7 +1,7 @@
// mixins for clearfix
// ------------------------
.clearfix() {
zoom: 1;
&::before,
&::after {
display: table;

View File

@ -70,4 +70,35 @@ describe('Switch', () => {
});
expect(checked.value).toBe(1);
});
it('customize checked value and children should work', async () => {
resetWarned();
const checked = ref(1);
const onUpdate = val => (checked.value = val);
const wrapper = mount({
render() {
return (
<Switch
{...{ 'onUpdate:checked': onUpdate }}
checked={checked.value}
unCheckedValue={1}
checkedValue={2}
checkedChildren="on"
unCheckedChildren="off"
/>
);
},
});
await asyncExpect(() => {
wrapper.find('button').trigger('click');
});
expect(checked.value).toBe(2);
expect(wrapper.find('.ant-switch-inner').text()).toBe('on');
await asyncExpect(() => {
wrapper.find('button').trigger('click');
});
expect(checked.value).toBe(1);
expect(wrapper.find('.ant-switch-inner').text()).toBe('off');
});
});

View File

@ -134,6 +134,7 @@ const Switch = defineComponent({
[`${prefixCls.value}-disabled`]: props.disabled,
[prefixCls.value]: true,
}));
return () => (
<Wave insertExtraNode>
<button
@ -160,7 +161,7 @@ const Switch = defineComponent({
>
{props.loading ? <LoadingOutlined class={`${prefixCls.value}-loading-icon`} /> : null}
<span class={`${prefixCls.value}-inner`}>
{checked.value
{checkedStatus.value
? getPropsSlot(slots, props, 'checkedChildren')
: getPropsSlot(slots, props, 'unCheckedChildren')}
</span>

View File

@ -115,6 +115,9 @@ const Mentions = {
const { measureText: prevMeasureText, measuring } = this.$data;
const { prefix = '', validateSearch } = this.$props;
const target = event.target;
if (target.composing) {
return;
}
const selectionStartText = getBeforeSelectionText(target);
const { location: measureIndex, prefix: measurePrefix } = getLastMeasureIndex(
selectionStartText,

View File

@ -1,7 +1,6 @@
import warning, { noteOnce } from '../../vc-util/warning';
import type { SelectProps } from '..';
import { convertChildrenToData } from './legacyUtil';
import type { OptionData } from '../interface';
import { toArray } from './commonUtil';
import type { RawValueType, LabelValueType } from '../interface/generator';
import { isValidElement } from '../../_util/props-util';
@ -36,23 +35,6 @@ function warningProps(props: SelectProps) {
'Please avoid setting option to disabled in tags mode since user can always type text as tag.',
);
// `combobox` & `tags` should option be `string` type
if (mode === 'tags' || mode === 'combobox') {
const hasNumberValue = mergedOptions.some(item => {
if (item.options) {
return item.options.some(
(opt: OptionData) => typeof ('value' in opt ? opt.value : opt.key) === 'number',
);
}
return typeof ('value' in item ? item.value : item.key) === 'number';
});
warning(
!hasNumberValue,
'`value` of Option should not use number type when `mode` is `tags` or `combobox`.',
);
}
// `combobox` should not use `optionLabelProp`
warning(
mode !== 'combobox' || !optionLabelProp,

View File

@ -196,7 +196,7 @@
"webpack": "^5.0.0",
"webpack-bundle-analyzer": "^4.0.0",
"webpack-cli": "^4.6.0",
"webpack-dev-server": "^3.1.14",
"webpack-dev-server": "^4.0.0",
"webpack-merge": "^5.0.0",
"webpackbar": "^5.0.0-3",
"xhr-mock": "^2.5.1"

View File

@ -130,7 +130,6 @@ module.exports = {
historyApiFallback: {
rewrites: [{ from: /./, to: '/index.html' }],
},
disableHostCheck: true,
hot: true,
open: true,
},