1.0.5 • Published 6 years ago
web-component-simple-program v1.0.5
Web Component Simple Program
A minimalist JS view library for Web Components inspired by Elm
Install with npm or yarn.
npm i web-component-simple-program
Example:
import {
Html,
HtmlAttributes,
HtmlEvents,
render
} from "web-component-simple-program";
const { div, text, button } = Html;
const { class_ } = HtmlAttributes;
const { onclick } = HtmlEvents;
const dom = div()([
span([class_("text-red")])([text("hello world")]),
button([onclick(e => console.log(e))])([text("Click Me")])
]);
render(document, dom);
Use the updateNode
helper to override the nodes attributes and children
import {
Html,
HtmlAttributes,
HtmlEvents,
updateNode,
render
} from "web-component-simple-program";
const { div, text, button } = Html;
const { class_, id } = HtmlAttributes;
const { onclick } = HtmlEvents;
const buttonHandler = _ => {
updateNode(document.getElementById("title"))([class_("text-green")])([
text("goodbye world")
]);
};
const dom = div()([
span([id("title"), class_("text-red")])([text("hello world")]),
button([onclick(buttonHandler)])([text("Click Me")])
]);
render(document, dom);
If managing state, I recommend using Program
(Inspired by The Elm Architecture)
import {
Html,
HtmlAttributes,
Program,
updateNode,
main
} from "web-component-simple-program";
const { div, text, button } = Html;
const { class_, id } = HtmlAttributes;
const { main, toModel, toMsg, toUpdate, Events } = Program;
const UpdateTitle = "@@app/UPDATE_TITLE";
const init = ({ title }) => toModel({ title });
const update = msg => model => {
switch (msg.payload) {
case UpdateTitle:
return toModel({ ...model, title: msg.payload.title });
default:
return toModel(model);
}
};
// Instead of using a Virtual DOM,
// viewUpdate (which is passed into toUpdate as the second argument)
// is called after the update function
// which allows manual changes to be made to the DOM for now
const viewUpdate = root => [
model =>
updateNode(root.getElementById("title"))([class_("text-green")])([
text(model.title)
]),
model =>
updateNode(root.getElementById("button"))()([
text("Click Me" + model.title)
])
];
const view = root => model => {
// Program Events intercept the HTMLEvents to handle async msg passing
// these events now take in a function that returns a Msg
// dispatch is also an added event if needed
// Ex. dispatch(toMsg(UpdateTitle, {title: "blah"}))
const { onclick } = Events(root);
return div()([
span([id("title"), class_("text-red")])([text(model.title)]),
button([
id("button"),
onclick(e => toMsg(UpdateTitle, { title: "goodbye world" }))
])([text("Click Me")])
]);
};
class MyCustomElement extends HTMLElement {
connectedCallback() {
const props = {
title: this.getAttribute("title") || ""
};
main(createRoot(this), {
init: init(props),
update: toUpdate(update, viewUpdate),
view
});
}
}
customElements.define("my-custom-element", MyCustomElement);