Next/Previous navigation of an Observable


I have an observable of blog posts, converted from an array:

let posts = Rx.Observable.fromArray(blogPosts)

And two observables nextClicks and prevClicks of button click events for next/previous navigate respectively:

What I want is:

  1. Initially the posts observable emits the very first post and then wait for click events
  2. posts emits next post when nextClicks emits (repeat current post if no next available)
  3. posts emits prev post when prevClicks emits (repeat current post if no prev available)

And I'm not sure if this is possible:

  1. Two observables postNextable and postPrevable, derived from posts, indicating whether there is a next/prev post available in posts respectively

Thanks in advance!




There are several ways to do 1, 2, 3 and 4. For number 4, I wonder how you plan to use those observables.

One way which only uses pure functions and no subjects is :

var blogPosts$ = Rx.Observable.just(blogPosts);
var index$ = Rx.Observable.merge(nextClicks, prevClicks)
             .withLatestFrom(blogPosts$, function(ev, blogPosts){return {posts: blogPosts, ev : ev};})
             .scan(function(index, posts_and_ev){
                     return isNextClick(posts_and_ev.ev) && isNextable(posts_and_ev.posts, index) ? index + 1 
                           :isPrevClick(posts_and_ev.ev) && isPrevable(posts_and_ev.posts, index) ? index - 1
                   }, 0);
var currentPost$ = index$.withLatestFrom(blogPosts$, function (index, blogPost){return blogPost[index]; }).startWith(blogPosts[0]);
var postNextable = index$.withLatestFrom(blogPosts$, function (index, blogPost){return isNextable(blogPost, index);});
var postPrevable = index$.withLatestFrom(blogPosts$, function (index, blogPost){return isNextable(blogPost, index);})

The output you seek is named here currentPost$.

Code test included thereafter. isNextable, isNextClick, isPrevable, isPrevClick have obvious semantics, and are easy to write (for example discriminating on key codes or button ids or else for your next and prev events). sample code