Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 pass data between 2 not related components

I have a questions about passing data in Angular.

First, I don't have a structure as <parent><child [data]=parent.data></child></parent>

My structure is

<container>   <navbar>     <summary></summary>     <child-summary><child-summary>   </navbar>   <content></content> </container> 

So, in <summary /> I have a select that do send value to <child-summary /> and <content />.

OnSelect method is well fired with (change) inside <summary /> component.

So, I tried with @Input, @Output and @EventEmitter directives, but I don't see how retrieve the event as @Input of the component, unless to go on parent/child pattern. All examples I've founded has a relation between component.

EDIT : Example with BehaviorSubject not working (all connected service to API works well, only observable is fired at start but not when select has value changed)

shared service = company.service.ts (used to retrieve company data)

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 (the "child")

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 (the trigerring "parent")

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);     } } 
like image 957
User.Anonymous Avatar asked Jun 07 '17 13:06

User.Anonymous


People also ask

How do you pass data between two unrelated components?

We will use a shared service, subject variable, and subscription variable to share data between unrelated components. We have added a subject variable inside the service. We will emit the data from one component using this subject variable. We can emit any type of data from subject variable.


1 Answers

This is a case where you want to use a shared service, as your components are structured as siblings and grandchildren. Here's an example from a video I created a video about sharing data between components that solves this exact problem.

Start by creating a BehaviorSubject in the service

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)   }  } 

Then inject this service into each component and subscribe to the observable.

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)   }  } 

You can change the value from either component and the value will be updated, even if you don't have the parent/child relationship.

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")   }  } 
like image 183
JeffD23 Avatar answered Sep 20 '22 07:09

JeffD23