组件输入上的双向数据绑定 属性

Bidirectional data binding on a component input property

我正在尝试在 angular2 上做一些事情,但我找不到关于此行为的信息。

我有一个应用程序实现了这样一个自定义组件:

import {Component,Input} from 'angular2/core'
    @Component({
      selector:'my-comp',
      template:`<input type="text" style="text-align:center; [(ngModel)]="inputText"> <p>{{inputText}}</p>`
    })

    export class MyComp{
      @Input() inputText : string;
    }

我正在尝试对组件中的 inputText 变量进行双向数据绑定,如下所示:

<my-comp [(inputText)]="testString"></my-comp>

其中 testString 是在 MyApp.ts 中定义的变量,其中包含一个字符串。当我的 inputText 被用户修改时,我希望我的 testString 变量也被修改。

这是一个带有简单示例代码的 Plunker:https://plnkr.co/edit/zQiCQ3hxSSjCmhWJMJph?p=preview

有没有办法让它简单地工作?我是否必须在我的自定义组件和重载函数上实现 Angular2 class 才能使其像 ngModel 一样工作?我是否必须创建一个 inputTextChanged 类型的 EventEmitter 变量,当它改变时发出我的数据并做这样的事情:

<my-comp [inputText]="testString" (inputTextChanged)="testString = $event;"></my-comp>

提前致谢。

您的 Plunker 已包含 EventEmitter。缺少 @Output() 注释。要更改值调用 inputTextChanged.emit(newValue)(这也会更改 inputText 上的值)

如果将来有人搜索这个,我会结合@pixelbits 和@Günter Zöchbauer 的回答和评论,对我的问题做出明确的回答。

要使双向数据绑定适用于自定义变量,您需要根据以下内容创建组件。

MyComp.ts 文件:

import {Component,Input,Output,EventEmitter} from 'angular2/core'
@Component({
  selector:'my-comp',
  templateUrl:`<input type="text" style="text-align:center;"
     [ngModel]="inputText" (ngModelChange)="inputText=$event;inputTextChange.emit($event);">`
})

export class MyComp{
  @Input() inputText : string;
  @Output() inputTextChange = new  EventEmitter();
}

MyApp.ts 文件:

import {Component} from 'angular2/core'
import {MyComp} from './MyComp'

@Component({
  selector:'my-app',
  templateUrl:`<h1>Bidirectionnal Binding test </h1>
    <my-comp [(inputText)]="testString"></my-comp><p>
    <b>My Test String :</b> {{testString}}</p>`,
  directives:[MyComp]
})

export class MyApp{
  testString : string;
  constructor(){
    this.testString = "This is a test string";
  }
}

inputText 变量的双向数据绑定工作正常。 您可以评论答案以获得更漂亮或更简单的方式来实现此代码。

模板语法文档中的 Two-Way Binding with NgModel 部分对此进行了解释:

<input [(ngModel)]="currentHero.firstName">

Internally, Angular maps the term, ngModel, to an ngModel input property and an ngModelChange output property. That’s a specific example of a more general pattern in which it matches [(x)] to an x input property for Property Binding and an xChange output property for Event Binding.

We can write our own two-way binding directive/component that follows this pattern if we're ever in the mood to do so.

另请注意,[(x)] 只是 属性 绑定和事件绑定的语法糖:

[x]="someParentProperty" (xChange)="someParentProperty=$event"

在你的情况下,你想要

<my-comp [(inputText)]="testString"></my-comp>

所以你的组件必须有一个 inputText 输入 属性 和一个 inputTextChange 输出 属性(这是一个 EventEmitter)。

export class MyComp {
  @Input()  inputText: string;
  @Output() inputTextChange: EventEmitter<string> = new EventEmitter();
}

要通知父级更改,每当您的组件更改 inputText 的值时,发出一个事件:

inputTextChange.emit(newValue);

在您的方案中,MyComp 组件使用 [(x)] 格式将输入 属性 inputText 绑定到 ngModel,因此您使用事件绑定 (ngModelChange) 来接收更改通知,并且在该事件处理程序中,您将更改通知父组件。

在其他不使用 ngModel 的情况下,重要的是 emit() 每当 MyComp 组件中 属性 inputText 的值发生变化时触发一个事件。

我所做的是使用 属性,所以当我更改数据时,更改会自动发出

private _data: AnyType;
@Input()  get data(): AnyType{
    return this._data;
}
set data(value: AnyType) {
    this._data = value;
    this.dataChange.emit(this._data);
}
@Output() dataChange: EventEmitter<AnyType> = new EventEmitter();

在 html 中,您将使用 [(data)]

绑定 属性
<comp [(data)]="getData()"></comp>