-
Notifications
You must be signed in to change notification settings - Fork 4k
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
support auto error tips in reactive form / 表单增强:根据错误类型自动化的显示错误提示 #4523
Comments
Translation of this issue:Form Enhancements: according to the type of error automated display an error messageWhat problem does this feature solve?
It also brings an added benefit is that standardized error, allows us to maintain the unity of the global error, but also easy to replace, otherwise you imagine:
What does the proposed API look like?`` `Html `` `It has achieved a For users, it is necessary a good agreement two data:
For
`` export type MyValidationErrors = Record <string, MyErrorsOptions> export class MyValidators extends Validators { static mobile (control: AbstractControl): MyValidationErrors | null { if (isEmptyInputValue (value)) { ? Return isMobile (value) null: {mobile: {errorTip: 'Mobile phone number is not valid', actual: value}} |
关联 #4411 ,看看有没有办法在 |
确实感觉在模板中写出所有错误信息很麻烦。 所以我们项目中也是通过自定义Validators来实现类似的效果。
这其中有个name属性,是接受label值的,由于 我觉得如果这个 |
很好的设计,提几个建议
具体的代码部分可以等 PR 提出来之后,我再详细review |
我们的实现方式: <nz-form-control [nzValidateStatus]="formControl" [nzErrorTip]="errorTip">
<nz-date-picker
style="width: 100%"
[ngModel]="dateTime()"
(ngModelChange)="dateTimeChange($event)"
nzShowTime
[nzAllowClear]="!required"
[nzBorderless]="borderless"
[nzDisabled]="readOnly"
[ngStyle]="borderless ? { color: '#262626' } : {}"
[nzSuffixIcon]="borderless ? '' : 'calendar'"
/>
</nz-form-control>
<ng-template #errorTip let-control>
<lib-jsonform-error-renderer
[abstractControl]="control"
[errorTemplate]="errorTemplate"
></lib-jsonform-error-renderer>
<ng-template #errorTemplate let-errMsg="errMsg">
<div>
{{ errMsg }}
</div>
</ng-template>
</ng-template> lib-jsonform-error-renderer 组件: @Component({
selector: 'lib-jsonform-error-renderer',
standalone: true,
imports: [NgTemplateOutlet],
templateUrl: './error-renderer.component.html',
styleUrl: './error-renderer.component.css',
})
export class ErrorRendererComponent {
errorTemplate: InputSignal<TemplateRef<unknown>> = input.required();
abstractControl: InputSignal<AbstractControl> = input.required();
// 各个报错及报错信息
errors: WritableSignal<Record<string, string>> = signal({});
errorMessages: Signal<string[]> = computed(() => {
const errors = this.errors();
return Object.entries(errors).map(([_, value]) => {
return value;
});
});
constructor() {
effect(
() => {
const formControl = this.abstractControl();
const errorTemplate = this.errorTemplate();
if (formControl && errorTemplate) {
formControl.statusChanges
.pipe(startWith(formControl.status))
.subscribe((status) => {
switch (status) {
case 'INVALID':
this.errors.set(this.computedErrors(formControl));
break;
case 'VALID':
this.errors.set({});
}
});
}
},
{
allowSignalWrites: true,
},
);
}
private computedErrors(
abstractControl: AbstractControl,
): Record<string, string> {
const errors = abstractControl.errors;
if (!errors) {
return {};
}
return this.validatorAdapter(errors);
}
/**
* 适配 Angular 提供的 Validators
*
* https://angular.dev/api/forms/Validators#
*/
private validatorAdapter(errors: ValidationErrors): Record<string, string> {
const r: Record<string, string> = {};
Object.entries(errors).forEach(([key, value]) => {
switch (key) {
case 'min':
r[key] = `最小值不能低于 ${value.min}`;
break;
case 'max':
r[key] = `最大值不能超过 ${value.max}`;
break;
case 'required':
r[key] = '该项必填';
break;
case 'requiredTrue':
r[key] = '该项必选';
break;
case 'minlength':
r[key] = `最小长度不能低于 ${value.requiredLength}`;
break;
case 'maxlength':
r[key] = `最大长度不能超过 ${value.requiredLength}`;
break;
case 'pattern':
r[key] = '输入不合规';
break;
// case 'email':
// this.updateErrors(key, '邮箱格式不正确');
// break;
default:
// 其他报错均为自定义报错信息(自定义的 ValidatorFn)
if (typeof value !== 'string') {
console.error('该报错信息不是可读的字符串');
break;
}
r[key] = value;
break;
}
});
return r;
}
} @for (errMsg of errorMessages(); track $index) {
<ng-container
*ngTemplateOutlet="errorTemplate(); context: { errMsg: errMsg }"
>
</ng-container>
} |
What problem does this feature solve?
zorro
在8.x
的版本中,nzFormControl
支持了nzErrorTip
属性。每次表单验证错误的时候,自动显示错误提示信息,这是一个很棒的功能,但是它还可以变得更加方便!那就是
autoErrorTip
,它主要解决了目前nzErrorTip
还遗留的两个痛点。重复定义错误提示:也就是我每个用
nzFormControl
的地方,都要写上一句Input is required
又或者是Email is not valid
.处理多种错误类型的时候不是很方便,示例:
另外它还可以带来一个额外的好处,就是标准化错误提示,可以让我们全局的错误提示保持统一,也方便替换,否则你设想一下:
Email is not valid
, 要求你把所有这个提示改成The input is not valid E-mail!
。 这个时候,你就只能全局去替换了。What does the proposed API look like?
已经实现了一个
demo
: https://stackblitz.com/edit/ng-zorro-antd-auto-error-tip?file=src%2Fapp%2Fauto-error-tip.directive.ts实现思路其实挺简单的,就是比根据
NgControl
的错误类型,使用约定好的errorTipKey
找到对应的错误提示errorTip
,然后赋值给nzFormControl
的nzErrorTip
:对于使用者,需要预先约定好两个数据:
errorTipKey
和errorTipMap
, 优先级如下:@Input
的方式设置errorTipKey
和errorTipMap
zorro
内实现,可以换成全局配置)的方式设置errorTipKey
和errorTipMap
errorTipKey
和一组errorTipMap
对于
Angular
官方的Validators
, 我们有两种处理方式:在
errorTipMap
中根据错误类型声明对应的errorTip
,示例:自定义一个
MyValidators extends Validators
,示例:The text was updated successfully, but these errors were encountered: