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); } }
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.
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") } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With