Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 706
Smokey Dawson Avatar asked Mar 28 '18 03:03

Smokey Dawson


3 Answers

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);
    }
}
like image 127
Arun Redhu Avatar answered Oct 12 '22 00:10

Arun Redhu


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) =>
    ...
    )
}
like image 6
G. Siganos Avatar answered Oct 12 '22 02:10

G. Siganos


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;
  });
like image 2
joh04667 Avatar answered Oct 12 '22 00:10

joh04667