July 26, 2017

Mithril.js: What do the docs recommend?

Before reading a library or framework’s source code, it’s advisable to go through the documentation. Thankfully, Mithril’s size means reading through the main APIs is not that arduous a task. When reading the docs, you will often find notes from the author(s) recommending different ways of using the available features. This is useful when you read the source because you can more easily understand why certain bits of code exist. I’ve noted below five recommendations I came across during my latest round of reading the Mithril docs. I found more than five but I’ll go through the rest at a later time. The example code below each recommendation has been taken from the docs.

m("div#hello") // static

m("a.link[href=/]", { 
	class: currentURL === "/" ? "selected" : ""
}, "Home") // dynamic
var users = [
	{name: "John"},
	{name: "Mary"},
]

m("ul", users.map(function(u) { // <ul>
	return m("li", u.name)  //   <li>John</li>
				//   <li>Mary</li>
})) 
var isError = false

m("div", isError ? "An error occurred" : "Saved") // <div>Saved</div>
function(redrawService) {
	return function(root, component) {
		if (component === null) {
			redrawService.render(root, [])
			redrawService.unsubscribe(root)
			return
		}
		
		if (component.view == null && typeof component !== "function") throw new Error("m.mount(element, component) expects a component, not a vnode")
		
		var run = function() {
			redrawService.render(root, Vnode(component))
		}
		redrawService.subscribe(root, run)
		run()
	}
}
var state = {
    term: "",
    search: function() {
        // save the state for this route
        // this is equivalent to `history.replaceState({term: state.term}, null, location.href)`
        m.route.set(m.route.get(), null, {replace: true, state: {term: state.term}})

        // navigate away
        location.href = "https://google.com/?q=" + state.term
    }
}

var Form = {
    oninit: function(vnode) {
        state.term = vnode.attrs.term || "" // populated from the `history.state` property if the user presses the back button
    },
    view: function() {
        return m("form", [
            m("input[placeholder='Search']", {oninput: m.withAttr("value", function(v) {state.term = v}), value: state.term}),
            m("button", {onclick: state.search}, "Search")
        ])
    }
}

m.route(document.body, "/", {
    "/": Form,
})