Angular 4 передачи данных между 2 не связанными компонентами
У меня есть вопросы о передаче данных в Angular.
Во-первых, у меня нет структуры как <parent><child [data]=parent.data></child></parent>
Моя структура
<container>
<navbar>
<summary></summary>
<child-summary><child-summary>
</navbar>
<content></content>
</container>
Итак, в <summary/>
меня есть выборка, которая отправляет значение в <child-summary/>
и <content/>
.
Метод OnSelect хорошо запускается с (изменением) внутри компонента <summary/>
.
Итак, я попытался с @Input
, @Output
и @EventEmitter
, но я не вижу, как извлечь событие как @Input компонента, если только не перейти на родительский/дочерний шаблон. Все примеры, которые я основал, имеют отношение между компонентами.
РЕДАКТИРОВАТЬ: Пример с BehaviorSubject не работает (все подключенные службы к API работают хорошо, запускается только наблюдаемый при запуске, но не когда выбор имеет значение изменилось)
shared service = company.service.ts (используется для получения данных компании)
import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/toPromise';
@Injectable()
export class SrvCompany {
private accountsNumber = new BehaviorSubject<string[]>([]);
currentAccountsNumber = this.accountsNumber.asObservable();
changeMessage(accountsNumber: string[]) {
this.accountsNumber.next(accountsNumber);
}
private _companyUrl = 'api/tiers/';
constructor(private http: Http) { }
getSociete(): Promise<Response> {
let url = this._companyUrl;
return this.http.get(url).toPromise();
}
}
invoice.component.ts("ребенок")
import { Component, OnInit, Input } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { SrvInvoice } from './invoice.service';
import { SrvCompany } from '../company/company.service';
@Component({
selector: 'invoice',
templateUrl: 'tsScripts/invoice/invoice.html',
providers: [SrvInvoice, SrvCompany]
})
export class InvoiceComponent implements OnInit {
invoice: any;
constructor(private srvInvoice: SrvInvoice, private srvCompany: SrvCompany)
{
}
ngOnInit(): void {
//this.getInvoice("F001");
// Invoice data is linked to accounts number from company.
this.srvCompany.currentAccountsNumber.subscribe(accountsNumber => {
console.log(accountsNumber);
if (accountsNumber.length > 0) {
this.srvInvoice.getInvoice(accountsNumber).then(data => this.invoice = data.json());
}
});
}
//getInvoice(id: any) {
// this.srvInvoice.getInvoice(id).then(data => this.invoice = data.json());
//}
}
company.component.ts (тригерринг "родитель")
import { Component, Inject, OnInit, Input } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { SrvCompany } from './company.service';
@Component({
selector: 'company',
templateUrl: 'tsScripts/company/company.html',
providers: [SrvCompany]
})
export class CompanyComponent implements OnInit {
societes: any[];
soc: Response[]; // debug purpose
selectedSociete: any;
ville: any;
ref: any;
cp: any;
accountNumber: any[];
constructor(private srvSociete: SrvCompany)
{
}
ngOnInit(): void {
this.getSocietes();
}
getSocietes(): void {
this.srvSociete.getSociete()
.then(data => this.societes = data.json())
.then(data => this.selectItem(this.societes[0].Id));
}
selectItem(value: any) {
this.selectedSociete = this.societes.filter((item: any) => item.Id === value)[0];
this.cp = this.selectedSociete.CodePostal;
this.ville = this.selectedSociete.Ville;
this.ref = this.selectedSociete.Id;
this.accountNumber = this.selectedSociete.Accounts;
console.log(this.accountNumber);
this.srvSociete.changeMessage(this.accountNumber);
}
}
Ответы
Ответ 1
Это случай, когда вы хотите использовать общую услугу, так как ваши компоненты структурированы как братья и сестры и внуки. Вот пример из видео, я создал видео о обмениваться данными между компонентами, что решает эту точную проблему.
Начните с создания объекта BehaviorSubject в сервисе
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class DataService {
private messageSource = new BehaviorSubject("default message");
currentMessage = this.messageSource.asObservable();
constructor() { }
changeMessage(message: string) {
this.messageSource.next(message)
}
}
Затем введите эту службу в каждый компонент и подпишитесь на наблюдаемый.
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-parent',
template: `
{{message}}
`,
styleUrls: ['./sibling.component.css']
})
export class ParentComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
}
Вы можете изменить значение с любого из компонентов, и значение будет обновлено, даже если у вас нет отношения родительский/дочерний.
import { Component, OnInit } from '@angular/core';
import { DataService } from "../data.service";
@Component({
selector: 'app-sibling',
template: `
{{message}}
<button (click)="newMessage()">New Message</button>
`,
styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {
message:string;
constructor(private data: DataService) { }
ngOnInit() {
this.data.currentMessage.subscribe(message => this.message = message)
}
newMessage() {
this.data.changeMessage("Hello from Sibling")
}
}
Ответ 2
если компонент не связан с тем, что вам нужно использовать Сервис
https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service
Ответ 3
Для этого есть два решения.
-
Это можно сделать через общий сервис, используя функцию наблюдаемого.
-
Для этого вы можете использовать ngrx/store. Это похоже на арку Redux. Вы будете получать данные из состояния.
Ответ 4
Вот самый простой пример совместного использования данных между двумя независимыми компонентами с использованием генератора событий и службы.
fooobar.com/info/6685968/...