简体   繁体   中英

Sharing data returned from rest call between sibling components in Angular 4

This is my main component:

import { Component, OnInit } from '@angular/core';
import { MyService } from '../my-service.service';
import { DataShareService } from '../data-share-service.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {

  private myCustomer: Object;

  constructor(private myService: MyService) { }

  ngOnInit() {    
    this.getMyCustomerProfile();
    console.log("In Home: " + JSON.stringify(this.myCustomer)); // this prints undefined - why ?

    // this.dataShareService.currentCustomer.subscribe(customer => this.customer = customer);
    // this.dataShareService.changeCustomer(this.customer);
  }

  private getMyCustomerProfile(){
    this.myService.getProfile()
    .subscribe(
      customer => {
          this.myCustomer = customer;
          console.log("In Home: " + JSON.stringify(this.myCustomer)); // this prints the returned json properly
      },
      error => {
          console.log("Error fetching user profile!");
      });

     console.log("In Home: " + JSON.stringify(this.myCustomer)); // this prints undefined - why ?    
  }
}

MyService getProfile method is a rest call:

getProfile(){
  return this.http.get(this.config.myUrl + 'mycustomer/', this.options).map((response: Response) => response.json());
 }

Question 1: Why does the console.log inside getMyCustomerProfile's subscribe method prints the returned object json correctly but the other two console.log prints undefined ?

Question 2: Also, how do I share the returned Object in above component with Sibling component (and not child component) using shared service ?

I tried below, but its not working.

Shared Service:

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

@Injectable()
export class DataShareService {

  private customerSource = new BehaviorSubject<Object>("default customer");
  currentCustomer = this.customerSource.asObservable();

  constructor() { }

  changeCustomer(customer: Object){
    console.log("In Service: "+customer);
    this.customerSource.next(customer);
  }
}

Sibling:

import { Component, OnInit } from '@angular/core';
import { DataShareService } from '../data-share-service.service';

@Component({
  selector: 'app-sibling',
  templateUrl: './sibling.component.html',
  styleUrls: ['./sibling.component.css']
})
export class SiblingComponent implements OnInit {

  private myCustomer: Object;

  constructor(private dataShareService: DataShareService) { }

  ngOnInit() {
    this.dataShareService.currentCustomer.subscribe(customer => this.myCustomer = customer);
  }
}

The HTML Template for both HomeComponent and SiblingComponent is printing a property from the returned object:

Welcome {{myCustomer?.name}}

This prints correctly in HomeComponent but not in SiblingComponent . Meaning the data is not getting shared. I am not sure what am I doing wrong.

Thanks for reading!

  1. It's all asynchronous. When you use console.log outside subscribe (or basically outside the operator chain) it'll be called before any value is emitted and therefore it's undefined .

  2. Just assign the value into a property in the service class:

     .subscribe(customer => this.myService.myCustomer = customer) 

    If you need the sibling components to be able to react when the myCustomer changes asynchronously make it a BehaviorSubject (or ReplaySubject(1) would in this case do the same).

     .subscribe(customer => this.myService.myCustomer.next(customer)) 

Thanks to Martin for the inputs.

Updating my getMyCustomerProfile method to following worked:

 private getMyCustomerProfile(){
    this.myService.getProfile()
    .subscribe(
      customer => {
          this.dataShareService.changeCustomer(customer);
      },
      error => {
          console.log("Error fetching user profile!");
      });
  }

And subscribing the same in both Sibling and main component with the following line:

this.dataShareService.currentCustomer.subscribe(customer => this.customer = customer);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM