Skip to main content

Observable

Credits: This module is a reimplementation of Riot Observable made to support typings, OOP, nested observers, and debugging utility.

The idea behind this refactor is to add a global event emitter to your application and be able to create child-observers that can have their own namespaced events. You can also wrap an existing object and make it observable; it will have the exact same API.

Example#

import { Observable } from '@riot-tools/sak';
const observer = new Observable();
// or
const somethingToMakeAnObserver = {};const observer = new Observable(somethingToMakeAnObserver);
// with configurable optionsconst observer = new Observable(null, {
    // Can spy on the observer for debugging    spy: ({ fn, event, listener, context, args }) => {
        if (fn === 'trigger') {
            console.log(event, args, context);        }    }});
observer.on(ev, fn);observer.one(ev, fn);observer.off(ev, fn);observer.trigger(ev, fn);

Child observers#

Once an observer is instantiated, you can observe other components. This gives your component a limited observable API that ties into its parent observer.

const modal = {};
// those events can have namespaced prefixesobserver.observe(modal, 'modal');
observer.on('modal-open', () => {});
// Because modal is namespaced, it will automatically prefix the event name with `modal`modal.trigger('open');
// destroy when done;modal.cleanup();

Riot plugin#

You can install your observer onto your components as a plugin via riot.install. Any listeners that are attached via this.on or this.one are automatically cleaned up before a comonent unmounts.

Riot.install(component => observer.install(component));

component.riot


<something>
    ...
    <script>
        export default {
            onClick() {
                this.trigger('something-clicked');            },
            onMounted() {
                // will be automatically cleaned up before unmount                this.on('user-fetched', (user) => this.update({ user }));
                fetchUser();            }        }    </script></something>

You can also directly install the observer API on a specific component using the same function

<script>
    import { observer } from './events';
    export default observer.install({
        onBeforeMount: () => {}    });</script>