如何在Angular 2中将对象从一个组件传递到另一个组件?


69

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


2
您可以发布一些代码吗?通常,对于ng2中的这种情况,您可以使用模板局部变量,但是如果没有更多细节,很难说。
jlew 2015年

我发现此答案有帮助:stackoverflow.com/a/31037168/1341825
theUtherSide

Answers:


23

组件2,指令组件可以定义输入属性(@inputTypescript中的注释)。组件1可以将该属性从模板传递给指令组件。

看到这个SO答案如何在Angular2的主组件和细节组件之间进行内部通信?

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


我可以将其用于非父子组件吗?例如<navbar> </ navbar> <router-outlet> </ router-outlet>我希望router-outlet中的所有组件都可以访问navbar组件,这可能吗?
EgorkZe

1
@EgorkZe为了实现这一点,您要共享的对象必须位于这两个组件的公共父级中。您无法描述在兄弟组件之间共享对象的其他方法。
Lucio Mollinedo

64

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

@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 -角RC.2


2
你在做上帝的工作!对兄弟组件有什么建议吗?就我而言,我在根目录下有2个自举。HeaderComponent具有我想分享与身体成分搜索输入..
索尼克的灵魂

@SonicSoul,将数据放在父级的JavaScript引用类型中,或者,如果它们不共享父级,则将数据置于共享服务中。对于服务方法,您可以再次使用JavaScript引用类型或使用observables
Mark Rajcok '16

谢谢!我想服务路线..没想到居然把可观察就可以了
声魂

1
@Mark,我们已经通过您的博文学习了Angular1,并且再次知道您正在教我们Angular2,您很喜欢:)
谢谢

我在这里发表双向绑定例如:stackoverflow.com/questions/31026886/...
sancelot

17

您还可以将数据存储在带有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;
    }
}

您的答案太短了,但是对于没有父子组件的人来说,这是正确的答案。
本杰明·卢西达姆

这是一个好主意。我很高兴找到这个答案。如果您知道对象在页面上的许多组件中都在全局范围内使用,那就特别好。
Gherman

从其他页面进行设置后,当我访问getScope()时,它将返回“未定义”。它可以很好地设置变量,但无法将其取回!有任何想法吗?
kevaljarsania

无法理解的。
Tamaghna Banerjee

2

使用输出注释

@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);

1

来自组件

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
    }

}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.