Published
Edited
Jul 15, 2020
Importers
Insert cell
Insert cell
Insert cell
viewof counter = {
const Msg = folktale.adt.union.union('Msg', {
Increment() {
return {};
},
Decrement(title) {
return { title };
}
});

function update(message, model) {
if (!message) return [model, cmd.none];
return message.matchWith({
Increment: () => [model + 1, cmd.none],
Decrement: () => [model - 1, cmd.none]
});
}

function view(model, dispatch) {
const bind = events.bind(Msg, dispatch);
return h('div', {}, [
h('button', { on: { click: bind(Msg.Increment) } }, '+'),
h('div', {}, model),
h('button', { on: { click: bind(Msg.Decrement) } }, '-')
]);
}

return app({
view,
update,
init: () => 0
});
}
Insert cell
Insert cell
app = ({
view, // (model, dispatch) => vnode // call 'dispatch' with a message to trigger an update
update, // (message, model) => [model, [fn]]
init // () => model
}) => {
const container = html`<div id="tea-snabbdom-container"></div>`;

const main = (vnode, model) => {
// Render a new view
const newVnode = view(model, message => {
// Update the model upon incoming message
let newModel, commands;
[newModel, commands] = update(message, model);
// Uptate the view
main(wrapper, newModel);
// Execute side-effects
commands.forEach(f => (async () => f())());
});
// id must match the container definition
const wrapper = h('div#tea-snabbdom-container', {}, [newVnode]);
// Apply the new view
patch(vnode, wrapper);
// viewof interop: update the value
container.value = model;
// viewof interop: notify Observable of the new value
container.dispatchEvent(new CustomEvent("input", { bubbles: true }));
};

// Kick-start the main loop.
main(container, init());
// Return the container for Observable to render.
return container;
}
Insert cell
events = ({
// {on: {click: events.bind(Msg, dispatch)(Msg.OnClick)}}
bind(messageType, dispatch) {
return handlerOrMessage => {
if (messageType.hasInstance(handlerOrMessage)) {
return _ => dispatch(handlerOrMessage);
} else {
return e => dispatch(handlerOrMessage(e));
}
};
},
// const bind = events.bind(Msg, dispatch)
// ... {on: {input: bind(targetValue(Msg.OnInput)})}
targetValue(messageType) {
return e => {
return messageType(e.target.value);
};
}
})
Insert cell
debug = ({
trace: (msg, obj) => {
console.log(msg, obj);
return obj;
}
})
Insert cell
cmd = ({
none: []
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more