Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(form): support FormItem.status and FormItem.tips; scrollToFirstError can scroll to list form-item #2684

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export type CSSSelector = string;
export interface KeysType {
value?: string;
label?: string;
disabled?: string;
}

export interface HTMLElementAttributes {
Expand Down
4 changes: 2 additions & 2 deletions src/form/_example/base.vue
Original file line number Diff line number Diff line change
Expand Up @@ -181,12 +181,12 @@ export default {
],
description: [
{
validator: (val) => val.length >= 5,
validator: (val) => !!val && val.length >= 5,
message: '至少 5 个字,中文长度等于英文长度',
type: 'warning',
},
{
validator: (val) => val.length < 20,
validator: (val) => !val || val.length < 20,
message: '不能超过 20 个字,中文长度等于英文长度',
type: 'warning',
},
Expand Down
5 changes: 3 additions & 2 deletions src/form/form-item-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ export default {
},
/** 表单字段名称 */
name: {
type: [String, Number] as PropType<TdFormItemProps['name']>,
type: String,
default: '',
},
/** 是否显示必填符号(*),优先级高于 Form.requiredMark */
requiredMark: {
Expand All @@ -54,7 +55,7 @@ export default {
},
/** 校验状态,可在需要完全自主控制校验状态时使用 */
status: {
type: String,
type: String as PropType<TdFormItemProps['status']>,
default: '',
},
/** 校验状态图标,值为 `true` 显示默认图标,默认图标有 成功、失败、警告 等,不同的状态图标不同。`statusIcon` 值为 `false`,不显示图标。`statusIcon` 值类型为渲染函数,则可以自定义右侧状态图标。优先级高级 Form 的 statusIcon */
Expand Down
19 changes: 17 additions & 2 deletions src/form/form-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ export interface FormItemConstructor extends Vue {
form: FormInstance;
}

export function getFormItemClassName(componentName: string, name?: string) {
if (!name) return '';
return `${componentName}-item__${name}`.replace(/(\[|\]\.)/g, '_');
}

export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('form'), getGlobalIconMixins()).extend({
name: 'TFormItem',

Expand Down Expand Up @@ -89,7 +94,7 @@ export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('
classes(): ClassName {
return [
`${this.componentName}__item`,
`${this.componentName}-item__${this.name || ''}`,
getFormItemClassName(this.componentName, this.name),
{
[`${this.componentName}__item-with-help`]: this.help,
[`${this.componentName}__item-with-extra`]: this.extraNode,
Expand All @@ -98,7 +103,7 @@ export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('
},
extraNode() {
const list = this.errorList;
if (this.needErrorMessage && list && list[0] && list[0].message) {
if (this.needErrorMessage && list?.[0]?.message) {
return <div class={`${this.classPrefix}-input__extra`}>{list[0].message}</div>;
}
if (this.successList.length) {
Expand Down Expand Up @@ -182,6 +187,14 @@ export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('
errorMessages(): FormErrorMessage {
return this.form.errorMessage ?? this.global.errorMessage;
},

tipsClassNames(): ClassName {
return [
`${this.classPrefix}-form-item-tips`,
`${this.classPrefix}-tips`,
`${this.classPrefix}-is-${this.status || 'default'}`,
];
},
},

created() {
Expand Down Expand Up @@ -464,6 +477,7 @@ export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('

render(): VNode {
const helpNode = renderTNodeJSX(this, 'help');
const tipsNode = renderTNodeJSX(this, 'tips');
return (
<div class={this.classes}>
{this.getLabel()}
Expand All @@ -473,6 +487,7 @@ export default mixins(getConfigReceiverMixins<FormItemConstructor, FormConfig>('
{this.getSuffixIcon()}
</div>
{helpNode && <div class={`${this.classPrefix}-input__help`}>{helpNode}</div>}
{tipsNode && <div class={this.tipsClassNames}>{tipsNode}</div>}
{this.extraNode}
</div>
</div>
Expand Down
22 changes: 11 additions & 11 deletions src/form/form.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,27 @@ data | Object | {} | Typescript:`FormData` | N
disabled | Boolean | undefined | \- | N
errorMessage | Object | - | Typescript:`FormErrorMessage` | N
formControlledComponents | Array | - | Typescript:`Array<string>` | N
labelAlign | String | right | optionsleft/right/top | N
labelAlign | String | right | options: left/right/top | N
labelWidth | String / Number | '100px' | \- | N
layout | String | vertical | optionsvertical/inline | N
layout | String | vertical | options: vertical/inline | N
preventSubmitDefault | Boolean | true | \- | N
requiredMark | Boolean | true | \- | N
resetType | String | empty | optionsempty/initial | N
rules | Object | - | Typescript:`FormRules<FormData>` `type FormRules<T extends Data> = { [field in keyof T]?: Array<FormRule> }`。[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
scrollToFirstError | String | - | options''/smooth/auto | N
resetType | String | empty | options: empty/initial | N
rules | Object | - | Typescript:`FormRules<FormData>` `type FormRules<T extends Data = any> = { [field in keyof T]?: Array<FormRule> }`。[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
scrollToFirstError | String | - | options: ''/smooth/auto | N
showErrorMessage | Boolean | true | \- | N
statusIcon | Boolean / Slot / Function | undefined | Typescript:`boolean \| TNode<TdFormItemProps>`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
submitWithWarningMessage | Boolean | false | \- | N
onReset | Function | | Typescript:`(context: { e?: FormResetEvent }) => void`<br/> | N
onSubmit | Function | | Typescript:`(context: SubmitContext<FormData>) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface SubmitContext<T extends Data = Data> { e?: FormSubmitEvent; validateResult: FormValidateResult<T>; firstError?: string }`<br/><br/>`type FormValidateResult<T> = boolean \| ValidateResultObj<T>`<br/><br/>`type ValidateResultObj<T> = { [key in keyof T]: boolean \| ValidateResultList }`<br/><br/>`type ValidateResultList = Array<AllValidateResult>`<br/><br/>`type AllValidateResult = CustomValidateObj \| ValidateResultType`<br/><br/>`interface ValidateResultType extends FormRule { result: boolean }`<br/><br/>`type ValidateResult<T> = { [key in keyof T]: boolean \| ErrorList }`<br/><br/>`type ErrorList = Array<FormRule>`<br/> | N
onSubmit | Function | | Typescript:`(context: SubmitContext<FormData>) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface SubmitContext<T extends Data = Data> { e?: FormSubmitEvent; validateResult: FormValidateResult<T>; firstError?: string; fields?: any }`<br/><br/>`type FormValidateResult<T> = boolean \| ValidateResultObj<T>`<br/><br/>`type ValidateResultObj<T> = { [key in keyof T]: boolean \| ValidateResultList }`<br/><br/>`type ValidateResultList = Array<AllValidateResult>`<br/><br/>`type AllValidateResult = CustomValidateObj \| ValidateResultType`<br/><br/>`interface ValidateResultType extends FormRule { result: boolean }`<br/><br/>`type ValidateResult<T> = { [key in keyof T]: boolean \| ErrorList }`<br/><br/>`type ErrorList = Array<FormRule>`<br/> | N
onValidate | Function | | Typescript:`(result: ValidateResultContext<FormData>) => void`<br/>[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`type ValidateResultContext<T extends Data> = Omit<SubmitContext<T>, 'e'>`<br/> | N

### Form Events

name | params | description
-- | -- | --
reset | `(context: { e?: FormResetEvent })` | \-
submit | `(context: SubmitContext<FormData>)` | [see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface SubmitContext<T extends Data = Data> { e?: FormSubmitEvent; validateResult: FormValidateResult<T>; firstError?: string }`<br/><br/>`type FormValidateResult<T> = boolean \| ValidateResultObj<T>`<br/><br/>`type ValidateResultObj<T> = { [key in keyof T]: boolean \| ValidateResultList }`<br/><br/>`type ValidateResultList = Array<AllValidateResult>`<br/><br/>`type AllValidateResult = CustomValidateObj \| ValidateResultType`<br/><br/>`interface ValidateResultType extends FormRule { result: boolean }`<br/><br/>`type ValidateResult<T> = { [key in keyof T]: boolean \| ErrorList }`<br/><br/>`type ErrorList = Array<FormRule>`<br/>
submit | `(context: SubmitContext<FormData>)` | [see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`interface SubmitContext<T extends Data = Data> { e?: FormSubmitEvent; validateResult: FormValidateResult<T>; firstError?: string; fields?: any }`<br/><br/>`type FormValidateResult<T> = boolean \| ValidateResultObj<T>`<br/><br/>`type ValidateResultObj<T> = { [key in keyof T]: boolean \| ValidateResultList }`<br/><br/>`type ValidateResultList = Array<AllValidateResult>`<br/><br/>`type AllValidateResult = CustomValidateObj \| ValidateResultType`<br/><br/>`interface ValidateResultType extends FormRule { result: boolean }`<br/><br/>`type ValidateResult<T> = { [key in keyof T]: boolean \| ErrorList }`<br/><br/>`type ErrorList = Array<FormRule>`<br/>
validate | `(result: ValidateResultContext<FormData>)` | [see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts)。<br/>`type ValidateResultContext<T extends Data> = Omit<SubmitContext<T>, 'e'>`<br/>

### FormInstanceFunctions 组件实例方法
Expand All @@ -51,9 +51,9 @@ name | type | default | description | required
for | String | - | \- | N
help | String / Slot / Function | - | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
label | String / Slot / Function | '' | Typescript:`string \| TNode`。[see more ts definition](https://github.com/Tencent/tdesign-vue/blob/develop/src/common.ts) | N
labelAlign | String | - | optionsleft/right/top | N
labelAlign | String | - | options: left/right/top | N
labelWidth | String / Number | - | \- | N
name | String / Number | - | Typescript:`string \| number` | N
name | String | - | \- | N
requiredMark | Boolean | undefined | \- | N
rules | Array | - | Typescript:`Array<FormRule>` | N
showErrorMessage | Boolean | undefined | \- | N
Expand All @@ -79,8 +79,8 @@ number | Boolean | - | \- | N
pattern | Object | - | Typescript:`RegExp` | N
required | Boolean | - | \- | N
telnumber | Boolean | - | \- | N
trigger | String | change | optionschange/blur | N
type | String | error | optionserror/warning | N
trigger | String | change | options: change/blur | N
type | String | error | options: error/warning | N
url | Boolean / Object | - | Typescript:`boolean \| IsURLOptions` `import { IsURLOptions } from 'validator/es/lib/isURL'`。[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
validator | Function | - | Typescript:`CustomValidator` `type CustomValidator = (val: ValueType) => CustomValidateResolveType \| Promise<CustomValidateResolveType>` `type CustomValidateResolveType = boolean \| CustomValidateObj` `interface CustomValidateObj { result: boolean; message: string; type?: 'error' \| 'warning' \| 'success' }` `type ValueType = any`。[see more ts definition](https://github.com/Tencent/tdesign-vue/tree/develop/src/form/type.ts) | N
whitespace | Boolean | - | \- | N
Expand Down
Loading