Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to push to Observable of Array in Angular 4? RxJS

I have a property on my service class as so:

articles: Observable<Article[]>;

It is populated by a getArticles() function using the standard http.get().map() solution.

How can I manually push a new article in to this array; One that is not yet persisted and so not part of the http get?

My scenario is, you create a new Article, and before it is saved I would like the Article[] array to have this new one pushed to it so it shows up in my list of articles.

Further more, This service is shared between 2 components, If component A consumes the service using ng OnInit() and binds the result to a repeating section *ngFor, will updating the service array from component B simultaneously update the results in components A's ngFor section? Or must I update the view manually?

Many Thanks, Simon

like image 235
simon_www Avatar asked Nov 22 '17 00:11

simon_www


People also ask

How do you map an array to an observable?

To convert from array to observable you can use Rx. Observable. from(array) . To convert from observable to array, use obs.

How do I subscribe to an observable?

Subscribinglink An Observable instance begins publishing values only when someone subscribes to it. You subscribe by calling the subscribe() method of the instance, passing an observer object to receive the notifications. Returns an Observable instance that synchronously delivers the values provided as arguments.


2 Answers

As you said in comments, I'd use a Subject.

The advantage of keeping articles observable rather than storing as an array is that http takes time, so you can subscribe and wait for results. Plus both components get any updates.

// Mock http
const http = {
  get: (url) => Rx.Observable.of(['article1', 'article2']) 
}

const articles = new Rx.Subject();

const fetch = () => {
  return http.get('myUrl').map(x => x).do(data => articles.next(data))
}

const add = (article) => {
  articles.take(1).subscribe(current => {
    current.push(article);
    articles.next(current);
  })
}

// Subscribe to 
articles.subscribe(console.log)

// Action
fetch().subscribe(
  add('article3')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.2/Rx.js"></script>
like image 129
Richard Matsen Avatar answered Oct 10 '22 05:10

Richard Matsen


Instead of storing the whole observable, you probably want to just store the article array, like

articles: Article[]

fetch() {
    this.get(url).map(...).subscribe(articles => this.articles)
}

Then you can manipulate the articles list using standard array manipulation methods.

If you store the observable, it will re-run the http call every time you subscribe to it (or render it using | async) which is definitely not what you want.

But for the sake of completeness: if you do have an Observable of an array you want to add items to, you could use the map operator on it to add a specified item to it, e.g.

observable.map(previousArray => previousArray.concat(itemtToBeAdded))

like image 22
ehrencrona Avatar answered Oct 10 '22 05:10

ehrencrona