Skip to content

Helpers and Extensions

pelonpelon edited this page Oct 28, 2015 · 24 revisions

A collection of extensions to vanilla Mithril that you might find useful.


View Helpers

m.withValue = function (callback) {
  return m.withAttr('value', callback)
}

Component Helpers

m.initComponent

This helper allows you to create an instance of a component and manage it yourself. Useful for when you want explicit control over your component's lifecycle, e.g. you want to control when your controller gets initialized.

m.initComponent = function (component, options, content) {
  var controller = new component.controller(options)
  controller.render = function (options2, content2) {
    return component.view(controller, options2 || options, content2 || content)
  }
  return controller
}

Example use:

var UserList = {
  controller: function () { ... }
  view: function () { ... }
}
var App = {
  controller: function () {
    var ctrl = this
    ctrl.userList = m.initComponent(UserList, { users: [...] })
  },
  view: function (ctrl) {
    return m('.app', [
      m('h1', "My App"),
      ctrl.userList.render()
    ])
  }
}

Network Extensions

Helpers that deal with AJAX requests and the like.

m.deferred.resolve

This simple helper allows you to mock a promise with a successful value. Useful for AJAX cache layers and mocking server responses.

m.deferred.resolve = function (value) {
  var deferred = m.deferred()
  deferred.resolve(value)
  return deferred.promise
}

m.deferred.reject

This simple helper allows you to mock a rejected promise. Useful for mocking server responses.

m.deferred.reject = function (value) {
  var deferred = m.deferred()
  deferred.reject(value)
  return deferred.promise
}

Router Helpers

Router Wrapper

var Router = function(module, name) {
    return {
        controller: function() {
        	// Do something generic like calling Google Analytics from here
        	console.log("Router", name);
            return new module.controller();
        },
        view: module.view
    };
};

m.route(document.getElementById("page"), "/", {
    "/": Router(app, "app"),
    "/project/:id": Router(project, "project")
});

Events

Pub/Sub mixin - gist

Utilizes the browser eventsystem Usefull in cases where you need communication between independent components Registered events are automatically removed onunload with preserving any other onunload handler

var eventsMixin = function(target) {
	
	var _subscriptions = [];

    target.broadcast = function(type, payload) {
        var ev = new CustomEvent(type, {
            detail: payload,
            bubbles: true,
            cancelable: true
        });
        document.dispatchEvent(ev);
    };

    target.subscribe = function(type, callback, capture) {
    	_subscriptions.push([type, callback, capture]);
        document.addEventListener(type, callback, capture || false);
    };

    target.ignore = function(type, callback, capture) {
        _subscriptions.splice(_subscriptions.indexOf([type, callback, capture]), 1);
        document.removeEventListener(type, callback, capture || false);
    };

	// save a reference to a possible present unload method
	var _savedUnload = (target.onunload)? target.onunload : null;
	
	target.onunload = function() {
		while (_subscriptions.length) {
			document.removeEventListener.apply(document, _subscriptions.pop());
		}
		_savedUnload && _savedUnload();
	};

	return target;
};

Example Use:

var obervableObject = eventsMixin({});

var component1 = {
  controller: function(){
    observable.subscribe('myFancyEvent',function(e) {
      
    });
    
    observable.broadcast('myOtherEvent', 'data');
  }
}

var component2 = {
  controller: function(){
    observable.subscribe('myOtherEvent',function(e) {
      
    });
    
    observable.broadcast('myFancyEvent', 'data');
  }
}

m.prop with callback

var propCallback = function(store, callback){
  return function(value){
    if(arguments.length){
      callback(value);
      store = value;
    }
   return store;
  }
};

//which could then be use like so:
myDomDestroyer = propCallback('', function(){
  //destroy DOM
});

redraw on m.prop update

m.prop = function( value ){
    return function( input ){
        if( arguments.length ){
            value = input

            m.redraw()
        }

        return value
    }
}
Clone this wiki locally