Angular:从指令访问 FormControl
Posted
技术标签:
【中文标题】Angular:从指令访问 FormControl【英文标题】:Angular: access FormControl from Directive 【发布时间】:2019-02-21 07:09:26 【问题描述】:我想通过自定义指令将验证器动态添加到我的 FormControl。
@Directive(
selector: "[idNumber]",
)
export class IdNumberDirective implements OnInit
constructor(private formControl: FormControl)
ngOnInit()
this.addValidators(this.formControl);
addValidators(formControl: FormControl)
formControl.setValidators(Validators.compose(
[Validators.required,
Validators.minLength(3),
Validators.maxLength(8)
]
));
<mat-form-field>
<mat-label>label</mat-label>
<input matInput
[formControl]="idNumberFormControl"
[placeholder]="placeholder"
</mat-form-field>
我不需要引用 nativeElement(通过 ElementRef)。 我想引用 formControl... ...并像这样使用它:
// html with my custom directive 'idNumber' ////////
<custom-input-string
idNumber
[name]="'idNumber'"
[label]="Id Number"
[placeholder]="">
</custom-input-string>
// TS ////////
@ViewChild(CustomInputStringComponent) child: CustomInputStringComponent;
ngAfterViewInit()
setTimeout(() =>
this.child.insertIntoForm(this.signupForm);
, 0);
有什么想法吗? 谢谢大家。
【问题讨论】:
【参考方案1】:您可以通过 FormGroupDirective 在指令中访问 FormGroup 和 FormControl:
注意:在本例中,我正在选择国家/地区。
import FormGroupDirective from "@angular/forms";
然后:
constructor(private fg: FormGroupDirective)
// Access the FormGroup
console.log('My FormGroup values: ', this.fg.value);
// Access the FormControl
console.log('The selectedCountryCtrl: ', this.fg.control.controls.selectedCountryCtrl);
console.log('The selectedCountryCtrl value: ', this.fg.control.controls.selectedCountryCtrl.value);
// Access the variable/object directly
console.log('My FormControl selectedCountry value: ', this.fg.value.selectedCountry);
【讨论】:
【参考方案2】:这是使用指令将验证器附加到表单控件的示例。
Stackblitz
请注意,使用它会导致丢失所有之前的验证器。
constructor(
// Get the control directive
private control: NgControl
)
ngOnInit()
const abstractControl = this.control.control;
abstractControl && abstractControl.setValidators([Validators.required]);
【讨论】:
嗨,onEvent 不是每次都在 FormControl 的 valueChanges 上触发吗?我的意思是,当用户在 FormControl 中聚焦时按下任何键时,这个事件不会触发吗?没有办法在指令的 OnInit 方法中检查和设置这些验证器吗?谢谢。 是的,它确实会在每次击键时触发,但函数中的条件会阻止验证器被设置多次。这必须以这种方式完成,因为构造函数不知道该控件。您也可以使用 ngOnInit(),如在 this stackblitz 中,我已经更新了我的答案(因为它确实更清楚!) 太棒了!正是我想要的!谢谢! 这个答案效果很好,但我认为主要方面(使用NgControl
而不是 OP 的FormControl
)太有价值,不能留在外部链接(Stackblitz)。我建议我们将这部分直接放在答案中,就像@Suresh 在他的回答中所做的那样。【参考方案3】:
//TestAnythingsComponent.ts
import Component, OnInit from '@angular/core';
import FormControl, FormBuilder, FormGroup, Validators from '@angular/forms';
import IdNumberDirective from '../directives/IdNumberDirective.directive';
@Component(
selector: 'app-test-anythings',
templateUrl: './test-anythings.component.html',
styleUrls: ['./test-anythings.component.css'],
providers:[IdNumberDirective]
)
export class TestAnythingsComponent implements OnInit
testForm: FormGroup;
constructor(fb: FormBuilder, IdNumberDirective : IdNumberDirective)
this.testForm = fb.group(
idNumberFormControl : new FormControl(null,
Validators.compose([
Validators.required,
Validators.minLength(3),
Validators.maxLength(8),
IdNumberDirective.customValidator()
])
),
)
//IdNumberDirective.ts
import Directive, OnInit from '@angular/core';
import Validators, ValidatorFn, AbstractControl, ValidationErrors from '@angular/forms';
@Directive(
selector: '[idNumber]'
)
export class IdNumberDirective implements OnInit
constructor()
ngOnInit()
customValidator(): ValidatorFn
Validators.nullValidator
return (control: AbstractControl): ValidationErrors | null =>
//any condition to check control value
if (control.value != "Sachin")
//return key value pair of errors
return "customError": inValid: true, errMsg: 'Invalid Value' ;
return null;
//test-anythings.component.html
<form [formGroup]="testForm">
<input idNumber formControlName="idNumberFormControl" />
<div *ngIf="testForm.get('idNumberFormControl').invalid && testForm.get('idNumberFormControl').errors.customError.inValid"
style="color:red">
testForm.get('idNumberFormControl').errors.customError.errMsg
</div>
<button type="submit">submit</button>
</form>
【讨论】:
亲爱的 Sachin,您能否在您的代码中添加一些注释以帮助理解您的方法? 嗨 Artem,看看我上面的解决方案,请输入“Sachin”以消失错误消息,我已经尽力了,我是 Angular 新手。谢谢。【参考方案4】:如果您使用 NgControl 和构造函数 DI 注入,我们可以有一个指令适用于 formControlName 或模板驱动表单中的反应式表单的表单控件:
指令:
import Directive from "@angular/core";
import NgControl from "@angular/forms";
@Directive(
selector: '[my-directive]'
)
export class MyDirective
constructor(private el: ElementRef, private control : NgControl)
【讨论】:
嗨@Suresh,谢谢你的建议,但我需要更详细的解释。我能做到吗? this.addValidators(this.control);那行得通吗? PS:我不使用,也永远不会使用“模板驱动的表单”。 我们可以使用 NgControl 通过 DI 获得对表单控件实例的引用。您可以使用该实例访问表单控件方法 您能否用更多代码更新您的答案?另外 - 您的建议中的“私人 el:ElementRef”有什么意义? @PaxForce 在这种特殊情况下,private el: ElementRef
没有任何作用,您可以忽略它。但一般来说,ElementRef
会传递给每个指令,因此您可以访问底层元素,而像 this.el.nativeElement
这样的原生元素会从 DOM 返回 HTML 元素。就像在组件中使用 ViewChild
来引用 HTML 模板中的元素一样。以上是关于Angular:从指令访问 FormControl的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Angular 2.0 中使用 formControl 访问 Native HTML Input 元素
从“@angular/forms”导入 FormControl,FormGroup; [复制]
在新的 Angular 2 表单中将 NgModel 绑定到 FormControl
无法从'@angular/forms'导入“导入FormGroup,FormControl [重复]