【问题标题】:How to pass object from one component to another in Angular 2?如何在Angular 2中将对象从一个组件传递到另一个组件?
【发布时间】:2016-03-09 09:04:34
【问题描述】:

我有 Angular 组件,第一个组件使用第二个组件作为 指令。 它们应该共享相同的模型 object,该模型在第一个组件中初始化。 如何将该模型传递给第二个组件?

【问题讨论】:

  • 你能发布一些代码吗?通常,您在 ng2 中为此类事情使用模板局部变量,但如果您不提供更多细节,就很难说。
  • 我发现这个答案很有帮助:stackoverflow.com/a/31037168/1341825

标签: angular angular2-directives


【解决方案1】:

对于从父组件到子组件的单向数据绑定,使用 @Input 装饰器(如样式指南中的 recommended)在子组件上指定输入属性

@Input() model: any;   // instead of any, specify your type

并在父模板中使用模板属性绑定

<child [model]="parentModel"></child>

由于您正在传递一个对象(JavaScript 引用类型),因此您对父组件或子组件中的对象属性所做的任何更改都将反映在另一个组件中,因为两个组件都引用了同一个对象。我在Plunker 中展示了这一点。

如果在父组件中重新分配对象

this.model = someNewModel;

Angular 会将新对象引用传播到子组件(作为更改检测的一部分自动传播)。

唯一不应该做的是在子组件中重新分配对象。如果这样做,父对象仍将引用原始对象。 (如果您确实需要双向数据绑定,请参阅https://stackoverflow.com/a/34616530/215945)。

@Component({
  selector: 'child',
  template: `<h3>child</h3> 
    <div>{{model.prop1}}</div>
    <button (click)="updateModel()">update model</button>`
})
class Child {
  @Input() model: any;   // instead of any, specify your type
  updateModel() {
    this.model.prop1 += ' child';
  }
}

@Component({
  selector: 'my-app',
  directives: [Child],
  template: `
    <h3>Parent</h3>
    <div>{{parentModel.prop1}}</div>
    <button (click)="updateModel()">update model</button>
    <child [model]="parentModel"></child>`
})
export class AppComponent {
  parentModel = { prop1: '1st prop', prop2: '2nd prop' };
  constructor() {}
  updateModel() { this.parentModel.prop1 += ' parent'; }
}

Plunker - Angular RC.2

【讨论】:

  • 你在做上帝的工作!对兄弟组件有什么建议吗?在我的情况下,我在根级别引导了 2 个。 HeaderComponent 有一个搜索输入,我想与正文中的组件共享它..
  • @SonicSoul,将数据放在父级中的 JavaScript 引用类型中,或者,如果他们不共享父级,则将数据放在共享服务中。对于服务方法,您可以再次使用 JavaScript 引用类型或use observables
  • 谢谢!我正在尝试服务路线.. 没想到实际上将 Observable 放在上面
  • @Mark 我们已经通过你的帖子学习了 Angular1,并且再次知道你正在教我们 Angular2,你摇滚 :)
  • 我在这里发布了一个双向数据绑定示例:stackoverflow.com/questions/31026886/…
【解决方案2】:

组件2,指令组件可以定义一个输入属性(Typescript中的@input注解)。并且组件 1 可以将该属性从模板传递给指令组件。

看到这个 SO 答案How to do inter communication between a master and detail component in Angular2?

以及如何将输入传递给子组件。在您的情况下,它是指令。

【讨论】:

  • 我可以将它用于非父子组件吗?例如 我希望 router-outlet 中的所有组件都可以访问导航栏组件,这可能吗?
  • @EgorkZe 为了实现这一点,您共享的对象必须位于这两个组件的共同父级中。没有其他方法可以在兄弟组件之间共享对象,这就是您所描述的。
【解决方案3】:

您还可以使用 setter 将数据存储在服务中,然后通过 getter 获取数据

import { Injectable } from '@angular/core';

@Injectable()
export class StorageService {

    public scope: Array<any> | boolean = false;

    constructor() {
    }

    public getScope(): Array<any> | boolean {
        return this.scope;
    }

    public setScope(scope: any): void {
        this.scope = scope;
    }
}

【讨论】:

  • 你的答案太短,但它是正确的,没有父子组件。
  • 这是个好主意。我很高兴我找到了这个答案。如果您知道您的对象在整个页面的许多组件中几乎全局使用,那就特别好。
  • getScope() 在我从其他页面设置后访问它时返回“未定义”。它将变量设置得很好,但无法取回它!有什么想法吗?
  • 无法理解。
【解决方案4】:

来自组件

import { Component, OnInit, ViewChild} from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { dataService } from "src/app/service/data.service";
    @Component( {
        selector: 'app-sideWidget',
        templateUrl: './sideWidget.html',
        styleUrls: ['./linked-widget.component.css']
    } )
    export class sideWidget{
    TableColumnNames: object[];
    SelectedtableName: string = "patient";
    constructor( private LWTableColumnNames: dataService ) { 
       
    }
    
    ngOnInit() {
        this.http.post( 'getColumns', this.SelectedtableName )
            .subscribe(
            ( data: object[] ) => {
                this.TableColumnNames = data;
     this.LWTableColumnNames.refLWTableColumnNames = this.TableColumnNames; //this line of code will pass the value through data service
            } );
    
    }    
    }

数据服务

import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

@Injectable()
export class dataService {
    refLWTableColumnNames: object;//creating an object for the data
}

到组件

import { Component, OnInit } from '@angular/core';
import { dataService } from "src/app/service/data.service";

@Component( {
    selector: 'app-linked-widget',
    templateUrl: './linked-widget.component.html',
    styleUrls: ['./linked-widget.component.css']
} )
export class LinkedWidgetComponent implements OnInit {

    constructor(private LWTableColumnNames: dataService) { }

    ngOnInit() {
    console.log(this.LWTableColumnNames.refLWTableColumnNames);
    }
    createTable(){
        console.log(this.LWTableColumnNames.refLWTableColumnNames);// calling the object from another component
    }

}

【讨论】:

    【解决方案5】:

    使用输出注解

    @Directive({
      selector: 'interval-dir',
    })
    class IntervalDir {
      @Output() everySecond = new EventEmitter();
      @Output('everyFiveSeconds') five5Secs = new EventEmitter();
      constructor() {
        setInterval(() => this.everySecond.emit("event"), 1000);
        setInterval(() => this.five5Secs.emit("event"), 5000);
      }
    }
    @Component({
      selector: 'app',
      template: `
        <interval-dir (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()">
        </interval-dir>
      `,
      directives: [IntervalDir]
    })
    class App {
      everySecond() { console.log('second'); }
      everyFiveSeconds() { console.log('five seconds'); }
    }
    bootstrap(App);
    

    【讨论】:

      猜你喜欢
      • 2019-07-04
      • 2017-04-30
      • 1970-01-01
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多