Creating stream based on asynchronously loaded DOM in RxJS

javascript, rxjs

Solution

bookClickStream = booksHTMLStream
  .take 1
  .flatMap (bookElements) ->
    Rx.Observable.fromArray bookElements
  .flatMap (bookElement) ->
    Rx.Observable.fromEvent bookElement, 'click'

Haven't tested this code, but that is roughly the idea.

Problem

I load a set of items through an ajax call - this is my intial DOM: ``` <section class="books"> </section> ``` Through an AJAX call, I load some books from my server, returned as JSON, to create the following DOM structure: ``` <section class="books"> <section class="book"> .. </section> <section class"book"> .. </section> # and so on </section> ``` This is how I perform the AJAX call: ``` buttonClickStream = Rx.Observable.fromEvent queryButton, 'click' requestStream = buttonClickStream .map -> bookName = $('#query').val() "/books/list?book=#{bookName}" responseStream = requestStream .flatMap (requestUrl) -> disableForm() Rx.Observable.fromPromise $.getJSON(requestUrl) ``` And by subscribing to the `responseStream` (and transforming the JSON response to HTML), I add it to the DOM like so: ``` booksHTMLStream = responseStream .map (json) -> _.map(json.books, (book) -> bookTemplate(book)) bookHTMLStream.subscribe( (html) -> booksContainer.html(html) ) ``` Now, what I want to do is attach a stream for clicks on `<section class="book">` elements, which have been added to the DOM in the first value return from the `booksHTMLStream`. I know I can add this inside the `subscribe` block, but this reminds me of callback-soup - and I feel like I'm doing things the wrong way. I cannot add the steam initially since there are no `<section class="book">` elements at page load, so the stream never fires off any values. So, what I'm wondering is whether it's possible to asynchronously add sources to a stream, or if there's any good way to accomplish what I want without this turning into a messy callback-ish situation? Cheers :-)

Original source