How to communicate between component in Angular?

2020-01-22 12:34发布

问题:

I'm working on a web app project and I'm trying to use Angular, I get some problem with component communication. For example, how a parent component exchange data with child component, how to communicate between siblings components.

回答1:

If you are trying to communicate from a parent component to a child component, this is pretty clearly described using @Input and EventEmitters with @Output in the angular docs.

Angular 2 component interaction

As for communication across siblings, I posted an answer in a similar question that might help with the issue of sharing data across sibling components. Currently, i think the shared service method is the most efficient.

angular-2-sibling-component-communication



回答2:

Using a service:

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

@Injectable()
export class AppState {
  public _subject = new Subject<object>();
  public event = this._subject.asObservable();

  public publish(data: any) {
    this._subject.next(data);
  }
}

and you can publish event-like messages like this:

export class AppComponent {
  constructor(
    public appState: AppState
  ) {
    appState.publish({data: 'some data'});
  }
}

and you can subscribe to these events:

export class HomeComponent {
  constructor(
    public appState: AppState
  ) {
    appState.event.subscribe((data) => {
      console.log(data); // {data: 'some data'}
    });
  }
}


回答3:

  1. @Input and @Output

    If there are multipart components you can use @Input and @Output to exchange data. Document : https://angular.io/guide/component-interaction

    example: https://angular.io/generated/live-examples/component-interaction/eplnkr.html

  2. Dependency Injection

    you can store the data in Service, and then inject Service into the component which you want. such as "user.server.ts" in the example:

    https://angular.io/generated/live-examples/dependency-injection/eplnkr.html



回答4:

You will need to use dependency injection. Here is a small example: https://github.com/gdi2290/angular2do/blob/gh-pages/app/components/todo-item/todo-item.js



回答5:

There is Events API in angular which can do it for you.

Click here for more details on Events.

Below is a quick example I am currently using in my project. Hope it helps someone in need.

import { Events } from 'ionic-angular';

Usage :

  constructor(public events: Events) {
        /*=========================================================
        =  Keep this block in any component you want to receive event response to            =
        ==========================================================*/
        // Event Handlers
        events.subscribe('menu:opened', () => {
            // your action here
            console.log('menu:opened');
        });
        events.subscribe('menu:closed', () => {
            // your action here
            console.log('menu:closed');
        });
    }

    /*=====================================================
    = Call these on respective events - I used them for Menu open/Close          =
    ======================================================*/

    menuClosed() {
        // Event Invoke
        this.events.publish('menu:closed', '');
    }
    menuOpened() {
        // Event Invoke
        this.events.publish('menu:opened', '');
    }

  }


回答6:

Inter component communication can be achieved in AngularJS. In AngularJS we have something called as require property which needs to be mapped in the component. Follow the example below which will access the function addPane(parameter) of the component myTabs from the component myPane: -

Project structure:

HTML

  1. index.html
  2. my-tabs.html
  3. my-pane.html

JS

  1. script.js

script.js

angular.module('docsTabsExample', [])
    .component('myTabs', {
      transclude: true,
      controller: function MyTabsController() {
        var panes = this.panes = [];
        this.select = function(pane) {
          angular.forEach(panes, function(pane) {
            pane.selected = false;
          });
          pane.selected = true;
        };
        this.addPane = function(pane) {
          if (panes.length === 0) {
            this.select(pane);
          }
          panes.push(pane);
        };
      },
      templateUrl: 'my-tabs.html'
    })
    .component('myPane', {
      transclude: true,
      require: {          //This property will be used to map other component
        tabsCtrl: '^myTabs' // Add ^ symbol before the component name which you want to map.
      },
      bindings: {
        title: '@'
      },
      controller: function() {
        this.$onInit = function() {
          this.tabsCtrl.addPane(this);  //Calling the function addPane from other component.
          console.log(this);
        };
      },
      templateUrl: 'my-pane.html'
    });

index.html

<my-tabs>
  <my-pane title="Hello">
    <h4>Hello</h4>
    <p>Lorem ipsum dolor sit amet</p>
  </my-pane>
  <my-pane title="World">
    <h4>World</h4>
    <em>Mauris elementum elementum enim at suscipit.</em>
    <p><a href ng-click="i = i + 1">counter: {{i || 0}}</a></p>
  </my-pane>
</my-tabs>

my-tabs.html

<div class="tabbable">
  <ul class="nav nav-tabs">
    <li ng-repeat="pane in $ctrl.panes" ng-class="{active:pane.selected}">
      <a href="" ng-click="$ctrl.select(pane)">{{pane.title}}</a>
    </li>
  </ul>
  <div class="tab-content" ng-transclude></div>
</div>

my-pane.html

<div class="tab-pane" ng-show="$ctrl.selected" ng-transclude></div>

Code snippet : https://plnkr.co/edit/diQjxq7D0xXTqPunBWVE?p=preview

Reference: https://docs.angularjs.org/guide/component#intercomponent-communication

Hope this helps :)



回答7:

using DataService stackbliz

sender.ts

import { Component } from '@angular/core';
import {dataService} from './dataservice.service';
@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  //name = 'Angular';
  constructor(private SVC: dataService ){

  }
  sender(){
    this.SVC.name="sender"
    console.log("sending this string:    "+this.SVC.name)
  }

}

dataservice.ts

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

    @Injectable()
    export class dataService {
    name=""
      constructor() { }
    }

receiver.ts

import { Component, OnInit } from '@angular/core';
import {dataService} from '../dataservice.service';
@Component({
  selector: 'app-recieved',
  templateUrl: './recieved.component.html',
  styleUrls: ['./recieved.component.css']
})
export class RecievedComponent implements OnInit {
  constructor(private dataservice: dataService ){

  }
  ngOnInit() { 
  }
print(){
  console.log("recieved:    " +this.dataservice.name)
}
}