- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我创建了一个派生自 this blog post 的 Angular 组件.我有一个 react 形式,我想在表单控件上得到错误,组件本身会有一个程式化的错误消息,当控件有错误时它会呈现。但是,当我尝试将 NgControl 类注入(inject)到组件中时,我遇到了循环引用问题,那么我将如何访问控件上的错误?
这是当前的代码,它还没有完成,但它应该给出了我想要完成的事情的基本概念:
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>
最佳答案
我希望通过某种依赖注入(inject)或声明式的方式来做到这一点。由于我无法使用这些方法找到任何东西,因此我将分享我如何针对我的案例解决此问题。
我刚刚将 formGroup 作为输入参数添加到组件,随着 formControlName begin 传递,我能够获得对该控件的引用。
这是我的组件的最终结果
//Typescript code file for component
/// ... necessary imports
@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('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>
关于angular - 如何从实现 ControlValueAccessor 的组件中获取对 FormControl 的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43351218/
我已经使用日期、月份和年份的三个下拉菜单实现了一个日期选择器。日期选择器是一个实现了 ControlValueAccessor 并且运行良好的组件。但是,我希望当三个下拉菜单中的任何一个被触摸时,控件
我有这个组件使用 ControlValueAccessor .该组件有自己的内部表单,我找不到在哪里设置表单控件的初始值。 有人可以指出我正确的方向吗? import { Component, C
这是 stackblitz重现的组件/问题。 我构建了一个自定义输入组件: 获取用户对象数组以进行预输入过滤 将您的选择显示为标签 表单控件值是所选用户的数组 users[] 问题是 adding a
为什么当我使用 ControlValueAccessor 时,值不更新并以 react 形式反射(reflect)? 在我的应用程序中,我有一个表单: profileForm = new FormG
我将 Angular 9 与 Angular Material 一起使用,并且通过实现 ControlValueAccessor 接口(interface)来自定义控件。一切正常。 当表单无效时,在我
如果我在我的模板中放置一个实现 ControlValueAccessor 接口(interface)的自定义输入并像这样绑定(bind)到它的更改事件: 我的自定义输入不会在模糊时触发任何事件(
如果我在我的模板中放置一个实现 ControlValueAccessor 接口(interface)的自定义输入并像这样绑定(bind)到它的更改事件: 我的自定义输入不会在模糊时触发任何事件(
我有一个为模板驱动表单构建动态输入组件的指令。默认值由输入组件本身设置。 问题是设置默认值会导致表单被标记为脏。 如何在指令内部设置默认值而不将表单标记为脏? @Directive({ selec
我有这个自定义控件,其中包括一个选择组件。但在我的 react 形式中,值(value)永远不会传播。 有人可以帮我吗? 我的自定义控件: const SOME_SELECT_VALUE_ACCESS
我需要开发一个可重用的列表组件,它返回一个对象列表,一个简单的对象列表,那些应该被分配给 formGroup 对象值中的键。 有没有办法在 Angular 中做一个列表的自定义控件? 这是我尝试过的和
我已经实现了 ControlValueAccessor,如我正在关注的教程中所示。但是,我在其中实现 controlvalueaccessor 的组件似乎没有检测到对 ngModel 的任何更改。我错
我已经创建了一个简单的自定义 input我的 Angular 应用程序中的组件使用 ControlValueAccessor .所以,当我想创建一个表单 input元素,我不必调用 , 只能调用 .
ControlValueAccessors 在过去几个月突然出现在我面前,我对为什么或何时应该使用它们而不是使用 @Input 感到有些困惑。用我的 react 形式。 这是迄今为止我如何使用响应式(
Angular 版本:6.1 我正在尝试使用 Kara Erickson 所称的 Composite ControlValueAccessor 来实现自定义控件,如演示文稿中所示 Angular Fo
我想通过实现 ControlValueAccessor 创建自定义表单元素地址。 我正在尝试创建一个 AddressComponent,其中有多个输入字段。我想在如下所示的 react 形式中使用此组
我想通过实现 ControlValueAccessor 创建自定义表单元素地址。 我正在尝试创建一个 AddressComponent,其中有多个输入字段。我想在如下所示的 react 形式中使用此组
如我所描述in this answer ,我创建了一个自定义 ControlValueAccessor 指令来控制何时触发我的组件的 onChange 事件,并且一切正常,除了当我测试它时, regi
按比例缩小 plunkr:https://plnkr.co/edit/gGCiYjcq70xaewn3n22F?p=preview @Input() model: any; propagateChan
如果自定义组件是另一个组件下的包装器,我不确定如何使用它。 喜欢: ComponentA_withForm | --ComponentA1_withWrapperOfCustomInput |
当您在 ControlValueAccessor 中“写入值”时,为什么 ngOnChanges 没有被触发?我正在通过 registerOnChange 发出一些事件,但我在 ngOnChanges
我是一名优秀的程序员,十分优秀!