[Vue-rx] Pass Template Data Through domStreams in Vue.js and RxJS
domStreams
enable you to pass additional data along the stream that can be provided by the template (such as data coming from a v-for
rendering of an Array). You can then pluck
off the data from the stream and use it further down the stream.
<template> <section class="section"> <button class="button" :disabled="disabled$" v-stream:click="{subject: click$, data: 1}">{{buttonText$}}</button> <h2> {{name$}} </h2> <img v-stream:error="imageError$" :src="image$" alt=""> </section> </template> <script> import { from, of, merge, throwError } from 'rxjs'; import { exhaustMap, switchMap, pluck, map, mapTo, catchError, shareReplay, share, startWith } from 'rxjs/operators'; export default { name: 'app', domStreams: ['click$', 'imageError$'], subscriptions() { const createLoader = url => from(this.$http.get(url)).pipe(pluck('data')); const luke$ = this.click$.pipe( pluck('data'), map(id => `https://starwars.egghead.training/people/${id}`), exhaustMap(createLoader), catchError(() => of({name: 'Failed.. :('})), share() ); const name$ = luke$.pipe(pluck('name')); const loadImage$ = luke$.pipe( pluck('image'), map(src => `https://starwars.egghead.training/${src}`) ); const failImage$ = this.imageError$.pipe( mapTo(`http://via.placeholder.com/400x400`) ); const image$ = merge( loadImage$, failImage$ ) const disabled$ = merge( this.click$.pipe(mapTo(true)), luke$.pipe(mapTo(false)), ).pipe(startWith(false)); const buttonText$ = disabled$.pipe(map(b => (b ? 'Loading...' : 'Load'))); return { name$, image$, failImage$, disabled$, buttonText$ }; } }; </script>