How to pass array of objects in angular app from one component to another component

Viewed 10039

I am working on angular app. I want to array of objects from one component to another using service. I am using the following link Pass array of int in Angular Route

PassData.html

<div>
 <button type="button" [routerLink]="['/receive-data']">Pass Data</button>
</div>

PassData.ts

import ....
@Component({
  selector: 'app-PassData',
  templateUrl: './PassData.component.html',
  styleUrls: ['./PassData.component.css'],
  providers: [DataService]
})

constructor( private dataService: DataService) { }
export class PassData {
  passObjects : any[] = [{'name': 'John', 'city': 'paris'},{'name': 'Bob', 'city': 'london'}, {'name': 'Grim', 'city': 'paris'}];

  passDataToService() {
     this.dataService.storePassedObject(this.passObjects);
  }
    
}

ReceiveData.ts

@Component({
  selector: 'app-ReceiveData',
  templateUrl: './ReceiveData.component.html',
  styleUrls: ['./ReceiveData.component.css'],
  providers: [DataService]
})

export class ReceiveData implements OnInit {
  let selectedProducts = this.DataService.retrievePassedObject();
  console.log(JSON.stringify(selectedProducts)); // prints empty array
}

This is angular service DataService.ts

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

@Injectable()
export class DataService {

    allPassedData: any[] = [];
    constructor() {}
   
    storePassedObject(passedData) {
        this.allPassedData = passedData;
       
    }

    retrievePassedObject() {
        return this.allPassedData;
        
    }
}

Here there are two components, passedData and RecieveData and a service connecting them so data can be passed b/w them. My goal is to pass the data and print the passed data in ReceiveData Component. I am not sure how to structure the angular service when I retrieve the data I find it is empty.

I have registered in app.module.ts This is app.module.ts

import ...
@NgModule({
 declarations: [
  PassData,
  ReceieveData
 ],
 providers : [
DataService
 ]
})

export class AppModule { }

I know allPassedData: any[] = []; is making the data empty when I try to access the objects from receiveData it is reassigned to []. But how do I solve this problem?

2 Answers

Demo use BehaviorSubject

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class DataService {

  private paramSource = new BehaviorSubject(null);
  sharedParam = this.paramSource.asObservable();

  constructor() { }

  changeParam(param: any[]) {
    this.paramSource.next(param)
  }

}

import to components

constructor(private _dataService: DataService) { }

to change param

 this._dataService.changeParam("your parameter")

to read param

this._dataService.sharedParam.subscribe(param=>console.log(param))

Use the Subjects and Behaviour Subjects in Service. like below example. so in that case both the component can subscribe the service object and emit the data as well. so whenever one changes other will get that data.

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

@Injectable()
export class DataService {

allPassedData: BehaviourSubject<any> = new BehaviourSubject<any>([]);
constructor() {}

storePassedObject(passedData) {
    this.allPassedData.next(passedData);
   
}
// here instead of retrieve like this you can directly subscribe the property in your components
retrievePassedObject() {
    return this.allPassedData;
    
}
}

// Passed Component
 import ....
 @Component({
   selector: 'app-PassData',
   templateUrl: './PassData.component.html',
   styleUrls: ['./PassData.component.css'],
   providers: [DataService] // inject in module for singleton instance
 })

 export class PassData {

 passObjects : any[] = [{'name': 'John', 'city': 'paris'},{'name': 'Bob', 
 'city': 'london'}, {'name': 'Grim', 'city': 'paris'}];

 constructor(private dataService DataService){};

 passDataToService() {
   this.dataService. allPassedData.next(this.passObjects); // here you emit 
                                             the objects 
  }

}

 // Recieved Component
 @Component({
  selector: 'app-ReceiveData',
  templateUrl: './ReceiveData.component.html',
  styleUrls: ['./ReceiveData.component.css'],
  providers: [DataService] // instead of injecting service in component inject 
                            in module for sigleton instance.
})

export class ReceiveData implements OnInit {
 selectProducts: any;
 constructor(private dataService DataService){};

 ngOnInit(){
 this.dataService.allPassedData.subscribe((allPassedData)=>{
   this.selectProducts = allPassedData;
   console.log(JSON.stringify(this.selectedProducts)); // print the data
 }) 
}

import ...
@NgModule({
 declarations: [
 PassData,
 ReceieveData
 ],
providers : [
  DataService
 ]
})

Hope it will help.

Related