子组件中的 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;
    

问题是当我在输入框中输入时,&lt;p&gt; 中的值会自动更改,而父组件的 &lt;h1&gt; 中的值不会更改。

【问题讨论】:

不要注入组件,你使用@Inputangular.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 手动实现ngModal数据双向绑定

在 Angular 2 中加载第一页时设置 [(ngModel)] 的值

在新的 Angular 2 表单中将 NgModel 绑定到 FormControl

Angular 4中的模板解析错误“没有将exportAs设置为ngModel的指令”