自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证 [英] Custom angular2 form input component with two way binding and validation inside a component

查看:36
本文介绍了自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法制作一个双向绑定输入组件,它也可以在组件内部进行验证?

我想要实现的是拥有一个可以在表单中排列的组件,如下所示:

<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></表单>

我有以下设置,但不知道如何正确设置:

组件:

从 'angular2/core' 导入 {Component,Input, Output,EventEmitter}从'angular2/common'导入{FORM_DIRECTIVES};@成分({选择器:'我的表单输入',指令:[FORM_DIRECIVES],模板:`<input type="text" class="form-control" id="i1" required [ngModel]="inputModel" (ngModelChange)="onChangeInput($event)" ngControl="ctrl" #ctrl="ngForm"/><p>{{"字段有效吗?我想在这里做出一些决定:"+ctrl.valid}}</p>`})导出类 InputComponent {构造函数(){};@Input() inputField:string;@Input() inputModel: 对象;@Output() inputModelChange = new EventEmitter();onChangeInput(事件){this.inputModel=事件;this.inputModelChange.emit(事件);}}

应用:

//我们的根应用组件从 'angular2/core' 导入 {Component}从'angular2/common'导入{FORM_DIRECTIVES};从 './my.input' 导入 {InputComponent}@成分({选择器:'我的应用',提供者:[],模板:`<div><p>有没有办法使自定义的 2 路绑定表单输入组件也具有验证功能?</p><form #f="ngForm"><my-form-input [(inputModel)]="name" [inputField]="myFormInputName"></my-form-input><p>{{name}}</p></表单>

`,指令:[InputComponent,FORM_DIRECIVES]})出口类应用{构造函数(){this.name = 'Angular2'}}

我还做了一个 Plunker 来说明我的问题:http://plnkr.co/edit/0vXjHbQmv7v7EKQcLWaa?p=预览

解决方案

您可以将表单控件传递给您的组件来为输入创建专用控件.基于这个新控件,当它们的 valid 属性为 false 时显示错误:

@Component({选择器:'我的表单输入',指令:[FORM_DIRECIVES],模板:`<input type="text" class="form-control" id="i1"[ngModel]="输入模型"(ngModelChange)="onChangeInput($event)"[ngFormControl]="formCtrl.controls[inputField]"/><p>字段是否有效?我想做一些决定这里取决于:{{formCtrl.controls[inputField].valid}}</p>`})导出类 InputComponent 实现 OnInit {@Input() inputField:string;@Input() formCtrl;@Input() inputModel: 对象;@Output() inputModelChange = new EventEmitter();ngOnInit() {this.formCtrl.control.addControl(this.inputField, new Control('', Validators.required));}onChangeInput(事件){this.inputModel=事件;this.inputModelChange.emit(事件);}}

您需要使用 addControl 方法使整个表单的状态与您在输入组件中创建的控件保持一致.

在您的情况下,您使用 ngControl 指令内联定义控件.我做了一些测试,但我不能让它以这种方式工作...

这里是从父组件使用这个组件的方法:

@Component({选择器:'我的应用',模板:`<form #f="ngForm"><my-form-input [(inputModel)]="name" [inputField]="myFormInputName" [formCtrl]="f"></my-form-input></表单>`,指令:[FORM_DIRECTIVES, InputComponent]})导出类 AppComponent {}

刚启动后仍然是一个检查问题.表单的全局状态未更新,出现以下错误:

表达式 '有效 : AppComponent@1:24' 中的 {{f.valid}} 在检查后已更改.以前的值:'有效:真'.当前值: '有效:假'

要解决这个问题,请查看基于 ChangeDetectorRef 类及其 detectChanges 方法的 Julien 的答案...

这是一个示例 plunkr:https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=预览.

Is there a way to make a two way binding input component, that can also have a validation inside the component?

What I'm trying to achieve is to have a components that I could line up in my forms as follows:

<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>

I have a following setup and can't figure out, how to make it right:

The component:

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);
  }
}

The app:

//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'
  }
}

I also made a Plunker to ilustrate my problem: http://plnkr.co/edit/0vXjHbQmv7v7EKQcLWaa?p=preview

解决方案

You can pass the form control to your component to create a dedicated control for the input. Based on this new control to display errors when their valid attributes are 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);
  }
}

You need to use the addControl method to make the state of your whole form consistent with controls you created within your input components.

In your case, you define your controls inline using the ngControl directive. I made some tests but I can't make it work this way...

Here is the way to use this component from the parent one:

@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 {
}

It remained a check problem just after starting. The global state of the form wasn't updated and the following error occured:

Expression '
    Valid : {{f.valid}} in AppComponent@1:24' has changed after it was checked. Previous value: '
    Valid : true'. Current value: '
    Valid : false'

To fix this aspect, have a look at the Julien's answer based on the ChangeDetectorRef class and its detectChanges method...

Here is a sample plunkr: https://plnkr.co/edit/Z4uOUq2q4iXdpo0J6R1o?p=preview.

这篇关于自定义 angular2 表单输入组件,在组件内具有两种方式绑定和验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆