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:
@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
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
- index.html
- my-tabs.html
- my-pane.html
JS
- 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)
}
}