angular – 如何从实现ControlValueAccessor的组件引用FormContr
发布时间:2020-12-17 06:59:26 所属栏目:安全 来源:网络整理
导读:我创建了一个从 this blog post派生的Angular组件.我有一个反应形式,我想在窗体控件上得到错误,组件本身将有一个程式化的错误消息,当控件有错误时它将呈现.但是,当我尝试将NgControl类注入组件时,我得到循环引用问题,那么我将如何访问控件上的错误? 这是当
我创建了一个从
this blog post派生的Angular组件.我有一个反应形式,我想在窗体控件上得到错误,组件本身将有一个程式化的错误消息,当控件有错误时它将呈现.但是,当我尝试将NgControl类注入组件时,我得到循环引用问题,那么我将如何访问控件上的错误?
这是当前的代码,它还没有完成,但它应该给出我想要完成的基本想法: import { Component,Output,EventEmitter,Input,forwardRef } from '@angular/core'; import { NgControl,NG_VALUE_ACCESSOR,ControlValueAccessor,Validator,AbstractControl,FormControl,NG_VALIDATORS } from '@angular/forms'; @Component({ selector: 'form-field-input',templateUrl: './form-field-input.component.html',styleUrls: ['./form-field-input.component.less'],providers: [{ provide: NG_VALUE_ACCESSOR,useExisting: forwardRef(() => FormFieldInputComponent),multi: true }] }) export class FormFieldInputComponent implements ControlValueAccessor { private propagateChange = (_: any) => { }; private propagateTouch = (_: any) => { }; @Input('label') label: string; @Input('type') type: string; @Input('id') id: string; @Input('formControlName') formControlName: string; @Input('error') error: string; @Input('classes') classes: any; private value: string; private data: any; constructor() { debugger; } private onChange(event) { this.data = event.target.value; this.propagateChange(this.data); this.propagateTouch(this.data); } writeValue(obj: any): void { this.data = obj; } registerOnChange(fn: any): void { this.propagateChange = fn; } registerOnTouched(fn: any): void { this.propagateTouch = fn; } } 模板文件: <div class="form-field-input-component"> <input id="{{id}}" type="{{type}}" class="form-field-input" [value]="data" (change)="onChange($event)" (keyup)="onChange($event)" /> <span class="context-icon fa fa-lock"></span> <span class="info-icon fa fa-info-circle"></span> <!-- I will have an NGIF here to check for errors before rendering the error --> <div class="form-error"> {{ error }} </div> </div> 解决方法
我希望通过某种依赖注入或声明式风格来做到这一点.由于我找不到任何使用这些方法的东西,我将分享我如何根据我的情况修复此问题.
我刚刚将formGroup作为输入参数添加到组件中,并且formControlName开始传递我能够获得对控件的引用. 这是我的组件的最终结果 //Typescript code file for component /// ... necessary imports @Component({ selector: 'form-field-input',multi: true }] }) export class FormFieldInputComponent implements ControlValueAccessor { private propagateChange = (_: any) => { }; private propagateTouch = (_: any) => { }; @Input('label') label: string; @Input('type') type: string; @Input('id') id: string; @Input('contextIconName') contextIconName: string; //Here I take in both the parent form and the form control name //in ngOnInit I throw if there is no parent form passed @Input('formControlName') formControlName: string; @Input('parentForm') parentForm: FormGroup; @Input('classes') classes: any; @Input('errorDefs') errorDefs: any; private error: string; private value: string; private data: any; private control: AbstractControl; constructor() {} ngOnInit() { if (!this.parentForm) { throw "Form Field input component must be a part of a form group" } //It ain't pretty but here we get access to the control and all of it's errors this.control = this.parentForm.get(this.formControlName); if (!this.control) { throw "Form Field input component must be a part of a form group" } } private setError() { if (this.errorDefs && this.control.errors) { var errorKeys = Object.keys(this.control.errors).filter(x => !!x); if (errorKeys) { var errorKey = errorKeys[0]; var error = this.errorDefs[errorKey] || null; this.error = error; return; } } this.error = null; } //Now on our on change event we can propagate the events //To the registered handlers,which should set the form field errors //and at the end we can check the reference to the control for those errors //so that we can display the appropriate messages private onChange(event) { this.data = event ? event.target.value : this.data; this.propagateChange(this.data); this.propagateTouch(this.data); this.setError(); } writeValue(obj: any): void { this.data = obj; } registerOnChange(fn: any): void { this.propagateChange = fn; } registerOnTouched(fn: any): void { this.propagateTouch = fn; } } //HTML template file <div class="form-field-input-component"> <input id="{{id}}" type="{{type}}" class="form-field-input {{class}}" [value]="data" (change)="onChange($event)" (keyup)="onChange($event)" (blur)="onChange($event)" /> <span class="context-icon fa {{contextIconName || 'fa-cog'}}"></span> <span class="info-icon fa fa-info-circle" *ngIf="error"></span> <div class="form-field-error" *ngIf="error"> {{ error }} </div> </div> //EXAMPLE USAGE: <form novalidate [formGroup]="myFormGroup"> <form-field-input formControlName="firstName" [parentForm]="myFormGroup" <!-- example: When the Validators.required sets it's error message we can map that to a user friendly error --> [errorDefs]="{ 'required': 'this field is required' }" <!-- Other inputs and stuff--> > </form-field-input> </form> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |