我希望在用户超过maxLength时通过动态向DOM添加<mat-error>来显示错误。
我已经有一个属性指令来限制输入字段的最大长度。我将它作为一个指令,因为它应用于项目中不同文件的许多输入字段。但现在问题是,当用户超出限制时,我必须显示mat-error。我不希望自己在所有文件的每个输入字段下添加<mat-error>,我想要一个模块化的解决方案。可以通过使用现有指令本身来完成吗?
<mat-form-field floatLabel="auto">
<input [formControl]="displayNameControl"
mongoIndexLimit
[charLength]="charLength"
matInput
name="displayName"
placeholder="Stack Name"
autocomplete="off"
required />
</mat-form-field>
这是我的指示
import { Directive, OnInit, NgModule, ElementRef, OnChanges, Input, SimpleChanges, Renderer2 } from '@angular/core';
@Directive({
selector: '[mongoIndexLimit]'
})
export class MongoIndexLimitDirective implements OnInit, OnChanges {
@Input() public charLength?: number;
private maxLength = 5;
constructor(
private el: ElementRef<HTMLElement>,
private renderer: Renderer2
) { }
public ngOnInit() {
this.el.nativeElement.setAttribute('maxLength', this.maxLength.toString());
}
public ngOnChanges(changes: SimpleChanges) {
if (changes.charLength.currentValue >= 5) {
const child = document.createElement('mat-error');
this.renderer.appendChild(this.el.nativeElement.parentElement.parentElement.parentElement, child);
}
}
}
当我尝试上面的时候我能够将一个<mat-error>元素附加到DOM,但angular不会将它视为编译器<mat-error>角度材质。它只是一个虚拟的<mat-error>,而不是一个材料组件。
我希望结果是一个带有maxLength设置的输入组件和一个动态生成的mat-error,它显示限制何时超出,就像下面的例子中的方式一样。
https://material.angular.io/components/input/examples(标题为自定义错误状态匹配器的输入)
对不起,我的英语不好 。
当然,您可以动态添加mat-error。关于这一点,NetBasal中有一个qazxsw poi。
我制作的一个简单的版本是在amazing article。在这个stackblitz中,我将指令附加到mat-form-field并进行解决,以附加新的组件mat-error-component。这允许我使用CSS和动画。
关键是使用ViewContainerRef使用ComponentFactoryResolver动态添加组件
嗯,指令的代码:
stackblitz
MatErrorComponent(为了方便起见,我把它称为它。可能需要放入主模块的entryComponents)看起来比实际更复杂因为“动画”,但实际上是一个export class MongoIndexLimitDirective implements AfterViewInit {
ref: ComponentRef<MatErrorComponent>;
constructor(
private vcr: ViewContainerRef,
private resolver: ComponentFactoryResolver,
private formField:MatFormField
) { }
public ngAfterViewInit()
{
this.formField._control.ngControl.statusChanges.subscribe(res=>this.onChange(res))
}
public onChange(res) {
if (this.formField._control.ngControl.invalid)
{
this.setError('error')
}
else
this.setError('')
}
setError(text: string) {
if (!this.ref) {
const factory = this.resolver.resolveComponentFactory(MatErrorComponent);
this.formField._elementRef
this.ref = this.vcr.createComponent(factory);
}
this.ref.instance.error=text;
}
<mat-error>{{message}}</mat-error>
更新了mat-error-component的更好方法。
我们可以考虑不同的错误并改善转换
@Component({
selector: 'custom-error',
template:`
<div [@animation]="_state" style="margin-top:-1rem;font-size:.75rem">
<mat-error >
{{message}}
</mat-error>
</div>
`,
animations: [
trigger('animation', [
state('show', style({
opacity: 1,
})),
state('hide', style({
opacity: 0,
transform: 'translateY(-1rem)'
})),
transition('show => hide', animate('200ms ease-out')),
transition('* => show', animate('200ms ease-in'))
]),
]
})
export class MatErrorComponent{
_error:any
_state:any
message;
@Input()
set error(value)
{
if (value && !this.message)
{
this.message=value;
this._state='hide'
setTimeout(()=>
{
this._state='show'
})
}
else{
this._error=value;
this._state=value?'show':'hide'
}
}
这允许当消息错误改变时,发生新的动画 - 在这种情况下,如果例如将不透明度从0改变为1。在我们的指令中将函数onChange更改为
@Component({
selector: '[custom-error]',
template: `
<div [@animation]="increment" *ngIf="show" style="margin-top:-1rem;font-size:.75rem">
<mat-error >
{{message}}
</mat-error>
</div>
`,
animations: [
trigger('animation', [
transition(':increment', [
style({ opacity: 0}),
animate('200ms ease-in', style({ opacity: 1 })),
]),
transition(':enter', [
style({ opacity: 0, transform: 'translateY(-1rem)' }),
animate('200ms ease-in', style({ opacity: 1, transform: 'translateY(0)' })),
]),
transition(':leave', [
animate('200ms ease-out', style({ opacity: 0, transform: 'translateY(-1rem)' }))
])])
]
})
export class MatErrorComponent {
show: boolean
message: string;
increment:number=0;
@Input()
set error(value) {
if (value)
{
if (this.message!=value)
this.increment++;
this.message = value;
}
this.show = value ? true : false;
}
}
见 public onChange(res) {
if (this.control.invalid)
{
if (this.control.errors.required)
this.setError(this.formField._control.placeholder+' required')
else
this.setError(this.formField._control.placeholder+' incorrect')
}
else
this.setError('')
}
你没有动态添加qazxsw poi,你只需把它放在那里。它与qazxsw poi严格合作,如果improve stackblitz将在mat-error
州,它将变得可见。
威胁它作为错误消息的容器。您所要做的就是调整消息(如果您可以拥有多个验证规则并希望所有这些规则都有自定义消息)。
来自Angular Material docs的代码
mat-form-field