add data to the end of a behavior object array Angular 5

25,372

Solution 1

You can add a new method to your service like addData in which you can combine your previous data with new data like.

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

@Injectable() 
export class UserService {
    userDataSource: BehaviorSubject<Array<any>> = new BehaviorSubject([]);

    userData = this.userDataSource.asObservable();

    updateUserData(data) {
        this.userDataSource.next(data);
    }

    addData(dataObj) {
        const currentValue = this.userDataSource.value;
        const updatedValue = [...currentValue, dataObj];
        this.userDataSource.next(updatedValue);
    }
}

Solution 2

For someone that may come accross this issue with a BehaviorSubject<YourObject[]>.

I found in this article a way to properly add the new array of YourObject

import { Observable, BehaviorSubject } from 'rxjs';
import { YourObject} from './location';
import { Injectable } from '@angular/core';
@Injectable({
    providedIn: 'root'
})
export class ObjService {
    private theObjData: BehaviorSubject<YourObject[]> = new BehaviorSubject<YourObject[]>(null);

    constructor() {
    }

    public SetObjData(newValue: YourObject[]): void {
        this.theObjData.next(Object.assign([], newValue));
    }
}

How to update data:

// inside some component
this.api.userData().subscribe((results:YourObject) => 
    this.objService.SetObjData(results);
)

How to observe changes on other component

// inside another component
ngOnInit() {
    this.objService.GetAccountStatements().subscribe((results) =>
    ...
    )
}

Solution 3

Normally Observables and Subjects are meant to be streams of data, not an assignment of data. BehaviorSubjects are different because they hold their last emitted value.

Normally Subjects or BehaviorSubjects inside of a contained class (like a Service) do not want to expose themselves publicly to any other classes, so it's best practice to access their properties with getters or methods. This keeps the data stream cold to all subscribers.

However, since the BehaviorSubject holds the last emitted value, there's a few options here. If all subscribers need a concatenated stream of data from every emission, you could access the last emitted value and append to it:

userDataSource = BehaviorSubject<any[]>([]);

userData = this.userDataSource.asObservable();

updateUserData(data) {

    this.userDataSource.next(this.userDataSource.value.push(data));
}

...or, in what might be considered better practice, Subscribers to this Subject could do their own transformation on the stream:

this.api.userData()
  .scan((prev, current) => prev.push(current). [])
  .subscribe((data) => { 
     this.concatenatedUserData = data;
  });
Share:
25,372
Smokey Dawson
Author by

Smokey Dawson

The Pride 560 Lift Chair is an electrically operated Smokey Dawson chair with reclining backrest, elevating leg-rest and a stand up function. Built with a steel and wooden frame and equipped with a single motor.

Updated on October 20, 2021

Comments

  • Smokey Dawson
    Smokey Dawson over 2 years

    I have some data that I want to be shared with my entire app so I have created a service like so..

    user.service

    userDataSource = BehaviorSubject<Array<any>>([]);
    
    userData = this.userDataSource.asObservable();
    
    updateUserData(data) {
        this.userDataSource.next(data);
    }
    

    then in my component Im getting some data from an api and then sending that data to userDataSource like so..

    constructor(
    private: userService: UserService,
    private: api: Api
    ){
    }
    
    ngOnInit() {
        this.api.getData()
          .subscribe((data) => { 
             this.userService.updateUserData(data);
          })
    }
    

    now that all works but.. I want to be able to add data to the end of the array inside the userDataSource so basically the equivalent of a .push am I able to just call the updateUserData() function and add more data or will doing that overwrite what is currently in there?

    Any help would be appreciated

  • darko99
    darko99 about 4 years
    Solved me an hour quest with this. In the end, I have condesed it like this: this.userDataSource$.next([...this.userDataSource$.value, dataObj]);
  • OJVM
    OJVM about 3 years
    this did not work for me private theObjData: BehaviorSubject<YourObject[]> = new BehaviorSubject<YourObject[]>(null); so i had to change it to private theObjData: BehaviorSubject<YourObject[]> = new BehaviorSubject<YourObject[]>([]); the problem was the null
  • Bulka
    Bulka almost 2 years
    Object.assign([], newValue) - tego potrzebowałam, dzięki wilekie !!