diff --git a/packages/web-vue/components/form/context.ts b/packages/web-vue/components/form/context.ts
index 83034e32a..bb0436808 100644
--- a/packages/web-vue/components/form/context.ts
+++ b/packages/web-vue/components/form/context.ts
@@ -32,6 +32,7 @@ export interface FormContext {
removeLabelWidth: (uid?: number) => void;
maxLabelWidth: number;
autoLabelWidth: boolean;
+ id?: string;
}
export interface FormItemContext {
diff --git a/packages/web-vue/components/form/form-item.vue b/packages/web-vue/components/form/form-item.vue
index 09d7641a8..5037cc87c 100644
--- a/packages/web-vue/components/form/form-item.vue
+++ b/packages/web-vue/components/form/form-item.vue
@@ -353,6 +353,9 @@ export default defineComponent({
const colProps = {
...(props.wrapperColProps ?? formCtx.wrapperColProps),
};
+ if (mergedId.value) {
+ colProps.id = mergedId.value;
+ }
if (props.labelColFlex || formCtx.autoLabelWidth) {
colProps.flex = 'auto';
}
@@ -365,6 +368,13 @@ export default defineComponent({
const mergedWrapperStyle = computed(
() => props.wrapperColStyle ?? formCtx.wrapperColStyle
);
+ const mergedId = computed(() => {
+ if (formCtx.id) {
+ return `${formCtx.id}_${field.value}`;
+ }
+ return field.value;
+ });
+
// 记录初始值,用于重置表单
const initialValue = getValueByPath(formCtx.model, props.field);
diff --git a/packages/web-vue/components/form/form.vue b/packages/web-vue/components/form/form.vue
index 5a824e416..a20ddf1eb 100644
--- a/packages/web-vue/components/form/form.vue
+++ b/packages/web-vue/components/form/form.vue
@@ -1,5 +1,5 @@
-
@@ -12,11 +12,15 @@ import {
provide,
reactive,
toRefs,
+ ref,
} from 'vue';
+import scrollIntoView, {
+ Options as ScrollIntoViewOptions,
+} from 'scroll-into-view-if-needed';
import { FormItemInfo, formInjectionKey } from './context';
import { getPrefixCls } from '../_utils/global-config';
import { Size } from '../_utils/constant';
-import { isArray, isFunction } from '../_utils/is';
+import { isArray, isFunction, isBoolean } from '../_utils/is';
import { FieldData, FieldRule, ValidatedError } from './interface';
import { useSize } from '../_hooks/use-size';
@@ -105,6 +109,21 @@ export default defineComponent({
type: Boolean,
default: false,
},
+ /**
+ * @zh 表单控件 `id` 的前缀
+ */
+ id: {
+ type: String,
+ },
+ /**
+ * @zh 验证失败后滚动到第一个错误字段
+ * @en Scroll to the first error field after verification fails
+ * @version 2.51.0
+ */
+ scrollToFirstError: {
+ type: Boolean,
+ default: false,
+ },
},
emits: {
/**
@@ -143,7 +162,9 @@ export default defineComponent({
},
setup(props, { emit }) {
const prefixCls = getPrefixCls('form');
+ const formRef = ref
();
const {
+ id,
model,
layout,
disabled,
@@ -219,6 +240,28 @@ export default defineComponent({
});
};
+ const scrollToField = (field: string, options?: ScrollIntoViewOptions) => {
+ const node = formRef.value || document.body;
+ const fieldId = props.id ? `${props.id}_${field}` : field;
+ const fieldNode = node?.querySelector(`#${fieldId}`);
+
+ if (fieldNode) {
+ scrollIntoView(fieldNode as HTMLDivElement, {
+ behavior: 'smooth',
+ block: 'nearest',
+ scrollMode: 'if-needed',
+ ...options,
+ });
+ }
+ };
+
+ const scrollToFirstError = (field: string) => {
+ const options = !isBoolean(props.scrollToFirstError)
+ ? props.scrollToFirstError
+ : undefined;
+ scrollToField(field, options);
+ };
+
const validate = (
callback?: (errors: undefined | Record) => void
): Promise> => {
@@ -238,6 +281,10 @@ export default defineComponent({
}
});
+ if (hasError && props.scrollToFirstError) {
+ scrollToFirstError(Object.keys(errors)[0]);
+ }
+
if (isFunction(callback)) {
callback(hasError ? errors : undefined);
}
@@ -271,6 +318,10 @@ export default defineComponent({
}
});
+ if (hasError && props.scrollToFirstError) {
+ scrollToFirstError(Object.keys(errors)[0]);
+ }
+
if (isFunction(callback)) {
callback(hasError ? errors : undefined);
}
@@ -295,6 +346,8 @@ export default defineComponent({
}
});
if (hasError) {
+ props.scrollToFirstError &&
+ scrollToFirstError(Object.keys(errors)[0]);
emit('submitFailed', { values: model.value, errors }, e);
} else {
emit('submitSuccess', model.value, e);
@@ -310,6 +363,7 @@ export default defineComponent({
provide(
formInjectionKey,
reactive({
+ id,
layout,
disabled,
labelAlign,
@@ -343,12 +397,14 @@ export default defineComponent({
return {
cls,
+ formRef,
handleSubmit,
innerValidate: validate,
innerValidateField: validateField,
innerResetFields: resetFields,
innerClearValidate: clearValidate,
innerSetFields: setFields,
+ innerScrollToField: scrollToField,
};
},
methods: {
@@ -405,6 +461,16 @@ export default defineComponent({
setFields(data: Record) {
return this.innerSetFields(data);
},
+ /**
+ * @zh 滚动到指定表单项
+ * @en Scroll to the specified form item
+ * @param {string} field
+ * @public
+ * @version 2.51.0
+ */
+ scrollToField(field: string) {
+ return this.innerScrollToField(field);
+ },
},
});
diff --git a/packages/web-vue/components/input-number/CHANGELOG.md b/packages/web-vue/components/input-number/CHANGELOG.md
index 606c536cc..492cb0f7f 100644
--- a/packages/web-vue/components/input-number/CHANGELOG.md
+++ b/packages/web-vue/components/input-number/CHANGELOG.md
@@ -2,6 +2,15 @@
changelog: true
```
+## 2.50.2
+
+`2023-08-25`
+
+### 💎 Enhancement
+
+- Optimize the long-press effect of the step button ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668))
+
+
## 2.49.0
`2023-07-21`
diff --git a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md
index 8e7044527..62987e3e4 100644
--- a/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md
+++ b/packages/web-vue/components/input-number/CHANGELOG.zh-CN.md
@@ -2,6 +2,15 @@
changelog: true
```
+## 2.50.2
+
+`2023-08-25`
+
+### 💎 功能优化
+
+- 优化步长按钮的长按效果 ([#2668](https://github.com/arco-design/arco-design-vue/pull/2668))
+
+
## 2.49.0
`2023-07-21`
diff --git a/packages/web-vue/components/input-number/input-number.tsx b/packages/web-vue/components/input-number/input-number.tsx
index c9a7a6c11..3279427c6 100644
--- a/packages/web-vue/components/input-number/input-number.tsx
+++ b/packages/web-vue/components/input-number/input-number.tsx
@@ -23,6 +23,7 @@ import { getKeyDownHandler, KEYBOARD_KEY } from '../_utils/keyboard';
type StepMethods = 'minus' | 'plus';
+const FIRST_DELAY = 800;
const SPEED = 150;
NP.enableBoundaryChecking(false);
@@ -400,7 +401,7 @@ export default defineComponent({
if (needRepeat) {
repeatTimer = window.setTimeout(
() => (event.target as HTMLElement).dispatchEvent(event),
- SPEED
+ repeatTimer ? SPEED : FIRST_DELAY
);
}
};
diff --git a/packages/web-vue/components/select/CHANGELOG.md b/packages/web-vue/components/select/CHANGELOG.md
index f08cd64fe..2e8b3ec29 100644
--- a/packages/web-vue/components/select/CHANGELOG.md
+++ b/packages/web-vue/components/select/CHANGELOG.md
@@ -2,6 +2,15 @@
changelog: true
```
+## 2.51.0
+
+`2023-09-01`
+
+### 🆕 Feature
+
+- support boolean type ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661))
+
+
## 2.47.1
`2023-06-09`
diff --git a/packages/web-vue/components/select/CHANGELOG.zh-CN.md b/packages/web-vue/components/select/CHANGELOG.zh-CN.md
index 8ec79da6b..180387ea7 100644
--- a/packages/web-vue/components/select/CHANGELOG.zh-CN.md
+++ b/packages/web-vue/components/select/CHANGELOG.zh-CN.md
@@ -2,6 +2,15 @@
changelog: true
```
+## 2.51.0
+
+`2023-09-01`
+
+### 🆕 新增功能
+
+- 支持`boolean` 类型 ([#2661](https://github.com/arco-design/arco-design-vue/pull/2661))
+
+
## 2.47.1
`2023-06-09`
diff --git a/packages/web-vue/components/select/README.en-US.md b/packages/web-vue/components/select/README.en-US.md
index 63f011aff..6b05e8ae8 100644
--- a/packages/web-vue/components/select/README.en-US.md
+++ b/packages/web-vue/components/select/README.en-US.md
@@ -53,8 +53,8 @@ description: When users need to select one or more from a group of similar data,
|Attribute|Description|Type|Default|version|
|---|---|---|:---:|:---|
|multiple|Whether to open multi-select mode (The search is turned on by default in the multi-select mode)|`boolean`|`false`||
-|model-value **(v-model)**|Value|`string\| number\| Record\| (string \| number \| Record)[]`|`-`||
-|default-value|Default value (uncontrolled mode)|`string\| number\| Record\| (string \| number \| Record)[]`|`'' \| []`||
+|model-value **(v-model)**|Value|`string\| number\| boolean\| Record\| (string \| number \| boolean \| Record)[]`|`-`||
+|default-value|Default value (uncontrolled mode)|`string\| number\| boolean\| Record\| (string \| number \| boolean \| Record)[]`|`'' \| []`||
|input-value **(v-model)**|The value of the input|`string`|`-`||
|default-input-value|The default value of the input (uncontrolled mode)|`string`|`''`||
|size|The size of the select|`'mini' \| 'small' \| 'medium' \| 'large'`|`'medium'`||
@@ -73,11 +73,11 @@ description: When users need to select one or more from a group of similar data,
|default-popup-visible|Whether the popup is visible by default (uncontrolled mode)|`boolean`|`false`||
|unmount-on-close|Whether to destroy the element when the dropdown is closed|`boolean`|`false`||
|filter-option|Whether to filter options|`boolean \| ((inputValue: string, option: SelectOptionData) => boolean)`|`true`||
-|options|Option data|`(string \| number \| SelectOptionData \| SelectOptionGroup)[]`|`[]`||
+|options|Option data|`(string \| number \| boolean \| SelectOptionData \| SelectOptionGroup)[]`|`[]`||
|virtual-list-props|Pass the virtual list attribute, pass in this parameter to turn on virtual scrolling [VirtualListProps](#VirtualListProps)|`VirtualListProps`|`-`||
|trigger-props|Trigger props of the drop-down menu|`TriggerProps`|`-`||
|format-label|Format display content|`(data: SelectOptionData) => string`|`-`||
-|fallback-option|Options that do not exist in custom values|`boolean\| (( value: string \| number \| Record ) => SelectOptionData)`|`true`|2.10.0|
+|fallback-option|Options that do not exist in custom values|`boolean\| (( value: string \| number \| boolean \| Record ) => SelectOptionData)`|`true`|2.10.0|
|show-extra-options|Options that do not exist in custom values|`boolean`|`true`|2.10.0|
|value-key|Used to determine the option key value attribute name|`string`|`'value'`|2.18.0|
|search-delay|Delay time to trigger search event|`number`|`500`|2.18.0|
@@ -90,15 +90,15 @@ description: When users need to select one or more from a group of similar data,
|Event Name|Description|Parameters|version|
|---|---|---|:---|
-|change|Triggered when the value changes|value: ` string \| number \| Record \| (string \| number \| Record)[] `||
+|change|Triggered when the value changes|value: ` string \| number \| boolean \| Record \| (string \| number \| boolean \| Record)[] `||
|input-value-change|Triggered when the value of the input changes|inputValue: `string`||
|popup-visible-change|Triggered when the display state of the drop-down box changes|visible: `boolean`||
|clear|Triggered when the clear button is clicked|-||
-|remove|Triggered when the delete button of the label is clicked|removed: `string \| number \| Record \| undefined`||
+|remove|Triggered when the delete button of the label is clicked|removed: `string \| number \| boolean \| Record \| undefined`||
|search|Triggered when the user searches|inputValue: `string`||
|dropdown-scroll|Triggered when the drop-down scrolls|-||
|dropdown-reach-bottom|Triggered when the drop-down menu is scrolled to the bottom|-||
-|exceed-limit|Triggered when multiple selection exceeds the limit|value: `string \| number \| Record \| undefined`
ev: `Event`|2.18.0|
+|exceed-limit|Triggered when multiple selection exceeds the limit|value: `string \| number \| boolean \| Record \| undefined`
ev: `Event`|2.18.0|
### `