Mithril JS

Einar Norðfjörð

@nordfjord

What is Mithril

Mithril is a client-side MVC framework - a tool to organize code in a way that is easy to think about and to maintain.

 

What is mithril?

Light-weight Robust Fast
12kb gzipped Safe-by-default templates Virtual DOM diffing and compilable templates
Small API Hierarchical MVC via components Intelligent auto-redrawing system
Small learning curve

How it compares

So how is it different?

  • code size
  • documentation
  • Architecture
  • View Layer Paradigm

Introduction to basic methods

  • m
  • m.mount
m(".container"); //<div class="container"></div>

m("#layout"); //<div id="layout"></div>

m("a[name=top]"); //<a name="top"></a>

m("[contenteditable]"); //<div contenteditable></div>

m("a#google.external[href='http://google.com']", "Google");
//<a id="google" class="external" href="http://google.com">Google</a>


m.mount(document.getElementById("content"), app);

Show me the code!

var app = {};

// notice the lack of boilerplate
app.view = function(){
    return m('h1', 'Hello World!');
};

// mount the application
m.mount(document.body, app);

Two Way Data Binding?

var app = {};
app.controller = function () {
    this.name = m.prop( '' );
};
app.view = function ( ctrl ) {
    return [
        m( 'input', {
            value: ctrl.name(),
            oninput: m.withAttr( 'value', ctrl.name )
        } ),
        m( 'h1', 'Hi ' + ctrl.name() )
    ];
};
m.mount( document.body, app );

Embracing Arrays

Users = {
    list: function(){
        return m.request({url: "users.json", method: "GET", initialValue: []});
    }
};
var app = {};
app.controller = function () {
    this.users = Users.list();
};
app.view = function ( ctrl ) {
    return m("ul", [
        ctrl.users().map(function(user){
            return m( "li", user.name + ": @" + user.username );
        })
    ]);
};
m.mount( document.body, app );

Embracing Functions

var app = {};
app.controller = function () {
    this.data = [];
    window.setInterval(function(){
        for(var i = 0; i < 100; ++i){
            this.data[i] = Math.random();
        }
        m.redraw();
    }.bind(this), 20);
};
app.view = function ( ctrl ) {
    return tableStyle(m('table', [
        m('thead', m('tr', [m('th', 'Key'), m('th', 'Value')])),
        m('tbody', [
            ctrl.data.map(function(value, index){
                return m('tr', [
                    m('td', index),
                    m('td', value)
                ]);
            })
        ])
    ]));
};
m.mount( document.body, app );
function tableStyle(vdom){
    vdom.attrs.className = 'table table-striped table-hover';
    return vdom;
}

Integrating with existing libraries

var Select2 = {
    view: function(f, ctrl) {
        return m("select", {config: Select2.config(ctrl)}, [
            ctrl.data.map(function(item) {
                return m("option", {value: item.id}, item.name);
            })
        ]);
    }
};

Select2.config = function(ctrl) {
    return function(element, isInitialized) {
        var el = $(element);

        if (!isInitialized) {
            el.select2()
                .on("change", function(e) {
                    if (typeof ctrl.onchange == "function") ctrl.onchange(el.select2("val"));
                    m.redraw();
                });
        }
        el.select2("val", ctrl.value);
    };
};

var app = {};

app.controller = function() {
    var data = [{id: 1, name: "John"}, {id: 2, name: "Mary"}, {id: 3, name: "Jane"}];
    var ctrl = {
        data: data,
        currentUser: data[1],
        changeUser: function(id) {
            ctrl.currentUser = data[id-1];
        }
    };
    return ctrl;
};

app.view = function(ctrl){
    return m("div", [
        m("label", "User:"),
        m.component(Select2, {data: ctrl.data, value: ctrl.currentUser.id, onchange: ctrl.changeUser})
    ]);
};

In Summary

Core Routing Data
m m.route m.request
m.prop m.route.param m.deferred
m.component m.sync
m.mount
m.withAttr
Rendering Html
m.render m.trust
m.redraw
m.startComputation
m.endComputation

deck

By Einar Norðfjörð