自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证
Custom angular2 form input component with two way binding and validation inside a component
有没有办法制作双向绑定输入组件,它也可以在组件内部进行验证?
我想要实现的是有一个组件,我可以在我的表单中排列如下:
<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
您可以将表单控件传递给您的组件,为输入创建专用控件。基于此新控件,当它们的 valid
属性为 false
:
时显示错误
@Component({
selector: 'my-form-input',
directives: [FORM_DIRECTIVES],
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'
要解决这个问题,请查看 Julien 基于 ChangeDetectorRef
class 及其 detectChanges
方法的答案...
这是一个示例 plunkr:https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=preview。
Thierry 的回答部分不错,因为在启用 ProdMode 时,您只是在隐藏问题:您没有刷新组件。
您必须在初始化表单组件后调用 "detectChange":
export class AppComponent {
constructor(private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.cdr.detectChanges();
}
}
有没有办法制作双向绑定输入组件,它也可以在组件内部进行验证?
我想要实现的是有一个组件,我可以在我的表单中排列如下:
<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
您可以将表单控件传递给您的组件,为输入创建专用控件。基于此新控件,当它们的 valid
属性为 false
:
@Component({
selector: 'my-form-input',
directives: [FORM_DIRECTIVES],
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'
要解决这个问题,请查看 Julien 基于 ChangeDetectorRef
class 及其 detectChanges
方法的答案...
这是一个示例 plunkr:https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=preview。
Thierry 的回答部分不错,因为在启用 ProdMode 时,您只是在隐藏问题:您没有刷新组件。
您必须在初始化表单组件后调用 "detectChange":
export class AppComponent {
constructor(private cdr: ChangeDetectorRef) {}
ngOnInit() {
this.cdr.detectChanges();
}
}