使用ComponentFactoryResolver
动态创建组件很简单,但是当我尝试对其中的Angular Material <mat-error>
组件执行此操作时,似乎并没有将创建的组件投影到父对象中<mat-form-field>
。我一直在使用带有Bootstrap组件的Netanel Basal的example,它非常适合生成表单控制错误,但是由于在Angular Material中与<mat-error>
一起使用的内容投射,我似乎无法理解适用于Angular Material v8.2.1。
是否可以在<mat-error>
中动态创建一个<mat-form-field>
并使其内容正确地投影?
答案 0 :(得分:1)
我之前尝试过-MatFormField通过MatError
拾取ContentChildren
。由于是内容投影,因此无法动态添加或删除诸如MatError
之类的元素-内容模板的编译和处理方式与其他模板不同。
您在评论中提到,您正在尝试处理模板之间的一致错误消息...为什么不向directive
元素添加<mat-error>
基于父控件的表单验证状态的错误消息?
但是,如果要控制模板,则不能使用指令。但是,您可以创建一个组件,并像指令一样使用:
@Component({
selector: '[matErrorMessages]',
template: '{{ error }}'
})
export class MatErrorMessagesDirective implements AfterViewInit {
public error = '';
private inputRef: MatFormFieldControl<MatInput>;
constructor(private _inj: Injector) { }
public ngAfterViewInit() {
// grab reference to MatFormField directive, where form control is accessible.
let container = this._inj.get(MatFormField);
this.inputRef = container._control;
// sub to the control's status stream
this.inputRef.ngControl.statusChanges.subscribe(this.updateErrors);
}
private updateErrors = (state: 'VALID' | 'INVALID') => {
if (state === 'INVALID') {
// active errors on the FormControl
let controlErrors = this.inputRef.ngControl.errors;
// just grab one error
const firstError = Object.keys(controlErrors)[0];
if(firstError === 'required')
this.error = 'This field is required.';
if(firstError === 'minlength')
this.error = 'This field should be longer.';
if(firstError === 'error from my own custom validator')
this.error = 'You get the point.';
// .....
}
}
然后进入模板。...
<mat-error matErrorMessages></mat-error>
这样,您可以像预期的那样,让MatFormField
控制MatError
的存在,但可以在本地化的地方控制错误元素的 content ,干净的方式。
stackblitz:https://stackblitz.com/edit/angular-sjkfft
您必须挖掘Material组件的私有成员,这是一个有问题的做法,并且可能会随着库更新的进行而中断,但这是可行的。
我实际上有一个针对此类错误消息的存储库,该存储库是为@ angular / material的较旧版本编写的,但是我也能够掌握Validator
本身,以实现更好的错误消息传递,并将该验证器的自定义验证器/错误的整个列表注入模块:https://github.com/joh04667/material-error-messages
答案 1 :(得分:0)
这是另一种替代解决方案,受ngx-valdemort
的启发,创建了一个用于处理控件验证错误消息的组件,只需要在formGroup主体中成为子组件并传递表单控件的名称即可,不仅限于角形材料分量。
@Component({
selector: 'error-summary',
templateUrl: './error-summary.component.html',
styleUrls: ['./error-summary.component.css']
})
export class ErrorSummaryComponent {
@Input() control:string;
@Input() visible:any;
constructor(private controlContainer: ControlContainer) { }
get form():FormGroup {
return this.controlContainer.control as FormGroup;
}
get formControl() :AbstractControl{
return this.form.get(this.control) as AbstractControl;
}
get isNotValid() {
return this.formControl.invalid && (this.formControl.touched || this.formControl.dirty)
}
}
模板
<ng-container *ngIf="isNotValid" >
<ng-container *ngIf="formControl.hasError('required')"> this is required </ng-container>
<ng-container *ngIf="formControl.hasError('email')">this not valid email format</ng-container>
<ng-container *ngIf="formControl.hasError('maxlength')">max ...</ng-container>
<ng-container *ngIf="formControl.hasError('minlength')">min ...</ng-container>
</ng-container>
并且可以像这样使用
<form [formGroup]="form">
<mat-form-field>
<input matInput placeholder="Enter your email" formControlName="email">
</mat-form-field>
<error-summary control="email" ></error-summary>
...
</form>