有没有办法制作双向绑定输入组件,也可以在组件内部进行验证?
我想要实现的是拥有一个我可以在我的表单中排列的组件,如下所示:
<form #f="ngForm"> <my-form-input [(inputModel)]="name" [inputField]="myFormInputName"></my-form-input> <my-form-input [(inputModel)]="name2" [inputField]="myFormInputName2"></my-form-input> ... <my-form-input [(inputModel)]="lastItem" [inputField]="lastItemName"></my-form-input> </form>
我有以下设置,无法弄清楚,如何使其正确:
组件:
import {Component,Input,Output,EventEmitter} from 'angular2/core' import {FORM_DIRECTIVES} from 'angular2/common'; @Component({ selector: 'my-form-input',directives: [FORM_DIRECTIVES],template: ` <input type="text" class="form-control" id="i1" required [ngModel]="inputModel" (ngModelChange)="onChangeInput($event)" ngControl="ctrl" #ctrl="ngForm"/> <p>{{"Is field valid? I would like to make some decisions here depending on that: "+ctrl.valid}}</p> ` }) export class InputComponent { constructor(){}; @Input() inputField:string; @Input() inputModel: Object; @Output() inputModelChange = new EventEmitter(); onChangeInput(event){ this.inputModel=event; this.inputModelChange.emit(event); } }
该应用程序:
//our root app component import {Component} from 'angular2/core' import {FORM_DIRECTIVES} from 'angular2/common'; import {InputComponent} from './my.input' @Component({ selector: 'my-app',providers: [],template: ` <div> <p>Is there a way to make a custom 2 way binding form input component having also validation?</p> <form #f="ngForm"> <my-form-input [(inputModel)]="name" [inputField]="myFormInputName"></my-form-input> <p>{{name}}</p> </form> </div> `,directives: [InputComponent,FORM_DIRECTIVES] }) export class App { constructor() { this.name = 'Angular2' } }
我还制作了一个Plunker来解决我的问题:http://plnkr.co/edit/0vXjHbQmv7v7EKQcLWaa?p=preview
您可以将表单控件传递给组件,以便为输入创建专用控件.基于此新控件在有效属性为false时显示错误:
@Component({ selector: 'my-form-input',template: ` <input type="text" class="form-control" id="i1" [ngModel]="inputModel" (ngModelChange)="onChangeInput($event)" [ngFormControl]="formCtrl.controls[inputField]"/> <p>Is field valid? I would like to make some decisions here depending on that: {{formCtrl.controls[inputField].valid}} </p> ` }) export class InputComponent implements OnInit { @Input() inputField:string; @Input() formCtrl; @Input() inputModel: Object; @Output() inputModelChange = new EventEmitter(); ngOnInit() { this.formCtrl.control.addControl( this.inputField,new Control('',Validators.required)); } onChangeInput(event){ this.inputModel=event; this.inputModelChange.emit(event); } }
您需要使用addControl方法使整个表单的状态与您在输入组件中创建的控件一致.
在您的情况下,使用ngControl指令定义控件内联.我做了一些测试,但我不能这样做……
以下是从父组件中使用此组件的方法:
@Component({ selector: 'my-app',template: ` <form #f="ngForm"> <my-form-input [(inputModel)]="name" [inputField]="myFormInputName" [formCtrl]="f"></my-form-input> </form> `,directives: [ FORM_DIRECTIVES,InputComponent ] }) export class AppComponent { }
刚开始后它仍然是一个检查问题.表单的全局状态未更新,发生以下错误:
Expression ' Valid : {{f.valid}} in AppComponent@1:24' has changed after it was checked. PrevIoUs value: ' Valid : true'. Current value: ' Valid : false'
要解决这个问题,请查看基于ChangeDetectorRef类及其detectChanges方法的Julien的答案……
这是一个样本plunkr:https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=preview.