Skip to content

Instantly share code, notes, and snippets.

@jacwright
Last active September 19, 2018 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save jacwright/da2e65e0cd83d8b2b0d32542202b7d3b to your computer and use it in GitHub Desktop.
Save jacwright/da2e65e0cd83d8b2b0d32542202b7d3b to your computer and use it in GitHub Desktop.
One `observe` for all svelte needs.
export function observe(key, callback, opts) {
const single = !Array.isArray(key);
const keypaths = single ? [ key ] : key;
const parts = keypaths.map(keypath => keypath.replace(/\[(\d+)\]/g, '.$1').split('.'));
const keys = parts.map(parts => parts[0]);
const fn = callback.bind(this);
let last = parts.map(parts => getNestedValue(this.get(), parts));
if (!opts || opts.init !== false) {
single ? fn(last[0], undefined) : fn(last, last.map(_ => undefined));
}
return this.on(
opts && opts.defer ? 'update' : 'state',
({ changed, current, previous }) => {
if (!previous) return; // prevent double-firing if observing in oncreate
let i = keys.length;
while (i--) {
if (changed[keys[i]]) {
let j = parts.length;
const values = parts.map(parts => getNestedValue(current, parts));
if (!values.every((value, i) => value === last[i])) {
single ? fn(values[0], last[0]) : fn(values, last);
last = values;
}
return;
}
}
}
);
}
function getNestedValue(obj, parts) {
for (let i = 0; i < parts.length; i += 1) {
if (!obj) return undefined;
obj = obj[parts[i]];
}
return obj;
}
@jacwright
Copy link
Author

This takes observe, observeDeep, and observeMany from https://github.com/sveltejs/svelte-extras and creates one observe method which supports all three. Without this, you cannot observe many and deep at the same time.

import { observe } from './svelte-observe';
component.observe = observe;

// Simple observe works as it ought
component.observe('simple', simple => {
  console.log('simple:', simple);
});

// Deep observe works as it should
component.observe('user.id', uid => {
  console.log('user id:', uid);
});

// Many and deep works together
component.observe(['user.id', 'user.isAdmin'], ([ uid, isAdmin ]) => {
  console.log('user id:', uid, 'admin?', isAdmin);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment