子组件中的 Angular 2 ngModel 更新父组件属性
Posted
技术标签:
【中文标题】子组件中的 Angular 2 ngModel 更新父组件属性【英文标题】:Angular 2 ngModel in child component updates parent component property 【发布时间】:2016-05-21 13:20:46 【问题描述】:我制作了一个简单的 UI,它包含两个组件(父组件和子组件)。
UI 的作用是当我在 Child 组件的输入框中键入一些内容时。该值将使用 ngModel 更改。
这样子组件可以正常工作。
// Child Component
@Component(
selector: 'child',
template: `
<p>sharedVar</p>
<input [(ngModel)]="sharedVar">
`
)
export class ChildComponent
sharedVar: string;
现在我有一个父组件,我打算使用与子组件相同的值。
我将子组件添加到父模板中,并使用依赖注入调用子组件的sharedVar
。
// Parent Component
@Component(
selector: 'parent',
template: `
<h1>sharedVar</h1>
<child></child>
`,
directives: [ChildComponent],
providers: [ChildCompnent]
)
export class ParentComponent
sharedVar: string;
constructor(child: ChildComponent)
this.sharedVar = child.sharedVar;
问题是当我在输入框中输入时,<p>
中的值会自动更改,而父组件的 <h1>
中的值不会更改。
【问题讨论】:
不要注入组件,你使用@Input
angular.io/docs/ts/latest/api/core/Input-var.html将值传递给子组件,模板创建的实例和你通过指定提供者创建的实例是两个不同的实例。跨度>
【参考方案1】:
如果你想在同一个组件中有多个双向数据绑定,你可以这样做
export class ComponentName
@Input() public first: string = '';
@Input() public second: string = '';
@Output() public firstChange = new EventEmitter();
@Output() public secondChange = new EventEmitter();
public functionName1(first: string): void
this.first = first;
this.firstChange.emit(first);
public functionName2(second: string): void
this.second = second;
this.secondChange.emit(second);
当输入和输出被命名为 'x' 和 'xChange' 时,它会在属于一起的父级中自动检测它们。
我认为这实际上是一种比已接受答案中的更好的做法,因为这里可以立即清楚地说明名称之间的关系。
【讨论】:
【参考方案2】:我们可以在父模板中使用[(x)]
语法来实现与子模板的双向数据绑定。如果我们创建一个名为xChange
的输出属性,Angular 会自动更新父属性。每当孩子更改值时,我们确实需要emit()
一个事件:
import Component, EventEmitter, Input, Output from 'angular2/core'
@Component(
selector: 'child',
template: `
<p>Child sharedVar: sharedVar</p>
<input [ngModel]="sharedVar" (ngModelChange)="change($event)">
`
)
export class ChildComponent
@Input() sharedVar: string;
@Output() sharedVarChange = new EventEmitter();
change(newValue)
console.log('newvalue', newValue)
this.sharedVar = newValue;
this.sharedVarChange.emit(newValue);
@Component(
selector: 'parent',
template: `
<div>Parent sharedVarParent: sharedVarParent</div>
<child [(sharedVar)]="sharedVarParent"></child>
`,
directives: [ChildComponent]
)
export class ParentComponent
sharedVarParent ='hello';
constructor() console.clear();
Plunker
我在 ParentComponent 中使用 sharedVarParent
只是为了证明父子组件中的名称不必相同。
【讨论】:
现在这只是纯金。这些信息应该在 angular.io 网站上 Cookbook/Component Interaction 部分的官方文档中。 太棒了!然而,这些更新一开始并没有发生在我的父母身上。显然,@Output() 事件的 var 名称与输入 var 完全相同,但后面带有“Change”,这一点非常重要。这是 Angular 在某处描述的吗? @deadconversations,是的,提到了here -- 向下滚动到第二个绿条注释。 如果父组件使用了 *ngFor 中的变量,它不会被更新。 那些正在寻找文档的人angular.io/guide/template-syntax#two-way-binding---【参考方案3】:您可以设置从子到父的事件发射器通信 (outputs
)。比如这样:
@Component(
selector: 'child',
template: `
<p>Child: sharedVar</p>
<input [(ngModel)]="sharedVar" (ngModelChange)="change()">
`
)
export class ChildComponent
@Output() onChange = new EventEmitter();
sharedVar: string;
change()
this.onChange.emit(value: this.sharedVar);
和父组件:
@Component(
selector: 'parent',
template: `
<h1>sharedVar</h1>
<child (onChange)="sharedVar = $event.value"></child>
`,
directives: [ChildComponent]
)
export class ParentComponent
sharedVar: string;
constructor()
演示: http://plnkr.co/edit/T2KH4nGKPSy6GEvbF1Nb?p=info
【讨论】:
他已经在使用@Output 的快捷方式和双向绑定。他只是使用providers: [ChildCompnent]
覆盖了它自己的组件。这是更简单的 imo:plnkr.co/edit/Qo0dMzDf9HeSGHnwhl2d?p=preview
@Langley,我没有看到父属性 sharedVar
在您的 plunker 中发生变化。我认为我们必须emit()
一个事件才能将更改提交给父级。
您可以通过在父模板中使用[(sharedVar)]
来简化此方法,然后将您的输出属性命名为sharedVarChange
。有兴趣的可以看我的回答。
@MarkRajcok 你是对的,我认为标签在父项中,在子项中输入,看起来只有在发送整个对象时才有效,我更改了示例以显示我的意思。它现在应该可以工作了。在某些情况下,可能是大多数情况下,您的方法会更好。以上是关于子组件中的 Angular 2 ngModel 更新父组件属性的主要内容,如果未能解决你的问题,请参考以下文章
将组件拆分成更小的组件,同时保持 Angular 中父组件的 `ngModel` 和 `ngModelChange` 绑定
Ionic Angular NgModel 错误引用了接口中的子对象
在 Angular 2 中加载第一页时设置 [(ngModel)] 的值