组件输入属性上的双向数据绑定
Posted
技术标签:
【中文标题】组件输入属性上的双向数据绑定【英文标题】:Bidirectional data binding on a component input property 【发布时间】:2016-04-09 02:35:59 【问题描述】:我正在尝试对 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 类才能使其像 ngModel
一样工作?我是否必须创建一个EventEmitter
类型的inputTextChanged
变量,当它发生更改时发出我的数据并执行以下操作:
<my-comp [inputText]="testString" (inputTextChanged)="testString = $event;"></my-comp>
提前谢谢你。
【问题讨论】:
是的,您必须创建一个事件发射器“inputTextChanged”,并在组件内部触发该事件。然后 [(inputText)] 应该按预期工作。 请注意:Angular2 中没有双向数据绑定之类的东西,但您可以有类似的行为。 victorsavkin.com/post/110170125256/… 根据官方网站的Angular2 Cheat Sheet:"[(something)]
只是一个属性绑定和一个事件绑定的语法糖。所以 Angular 不会将 [(something)]
视为一个双向数据绑定,而是将其视为两个单向数据绑定。
【参考方案1】:
这在模板语法文档的Two-Way Binding with NgModel 部分中进行了解释:
<input [(ngModel)]="currentHero.firstName">
在内部,Angular 将术语
ngModel
映射到ngModel
输入属性和ngModelChange
输出属性。这是一个更通用模式的具体示例,其中将[(x)]
匹配到属性绑定的x
输入属性和事件绑定的xChange
输出属性。如果我们有心情的话,我们可以编写自己的双向绑定指令/组件来遵循这种模式。
还要注意[(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 的其他场景中,重要的是每当 MyComp 组件中属性 inputText
的值发生变化时,emit()
一个事件。
【讨论】:
更新 Angular4:在子组件中不再需要指定 EventEmitter 输出。这是由@input 自动处理的。父视图:如果将来有人搜索此问题,我将结合 @pixelbits 和 @Günter Zöchbauer 的答案和 cmets 来明确回答我的问题。
要使双向数据绑定适用于自定义变量,您需要根据以下内容创建组件。
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
变量的双向数据绑定工作正常。
您可以评论答案以获得更漂亮或更简单的方式来实现此代码。
【讨论】:
【参考方案3】:您的 Plunker 已包含 EventEmitter
。缺少 @Output()
注释。要更改值调用inputTextChanged.emit(newValue)
(这也会更改inputText
上的值)
【讨论】:
是的,抱歉,我是 plunker 新手,忘记将 plunker 锁定到我希望您看到的状态,并继续对其进行测试,以便您看到我的修改。 我记得,我不知道你是否知道,但至少从 Angular2 的 beta 版本开始,“.next()”已被弃用,你应该使用“.emit()”。 谢谢!没见过。【参考方案4】:我所做的是使用一个属性,所以当我更改数据时,更改会自动发出
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>
【讨论】:
以上是关于组件输入属性上的双向数据绑定的主要内容,如果未能解决你的问题,请参考以下文章