【问题标题】:Angular 2 ngModel in child component updates parent component property子组件中的 Angular 2 ngModel 更新父组件属性
【发布时间】: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; 中的值不会更改。

【问题讨论】:

标签: typescript angular angular2-ngmodel


【解决方案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 中的变量,它不会被更新。
    【解决方案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 你是对的,我认为标签在父项中,在子项中输入,看起来只有在发送整个对象时才有效,我更改了示例以显示我的意思。它现在应该可以工作了。在某些情况下,可能是大多数情况下,您的方法会更好。
    猜你喜欢
    • 2017-05-18
    • 1970-01-01
    • 2016-06-05
    • 2018-02-13
    • 1970-01-01
    • 2021-02-10
    • 1970-01-01
    • 2017-02-15
    • 1970-01-01
    相关资源
    最近更新 更多