-
-
Notifications
You must be signed in to change notification settings - Fork 924
Helpers and Extensions
A collection of extensions to vanilla Mithril that you might find useful.
- View Helpers
- Component Helpers
- Network Extensions
- Database Connectivity
- Router Helpers
- Events
- Helpers for m.prop
- mithril-n - raw DOM nodes in Mithril templates
- Stephan Hoyer's collection of view helpers
m.withValue = function (callback) {
return m.withAttr('value', callback)
}
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, defaultOptions, defaultContent) {
var ctrl = new component.controller(options)
ctrl.render = function (options, content) {
return component.view(
controller,
options || defaultOptions,
content || defaultContent)
}
return ctrl
}
Example use:
var UserList = {
controller: function () { /* ... */ },
view: function () { /* ... */ }
}
var App = {
controller: function () {
this.userList = m.initComponent(UserList, {users: [ /* ... */ ]})
},
view: function (ctrl) {
return m('.app', [
m('h1', "My App"),
ctrl.userList.render()
])
}
}
Helpers that deal with AJAX requests and the like.
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
}
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
}
function Route(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"), "/", {
"/": Route(app, "app"),
"/project/:id": Route(project, "project")
})
See this gist.
Utilizes the browser's event system. Useful in cases where you need communication between independent components. Registered events are automatically removed with onunload while preserving any pre-existing onunload handler.
function eventsMixin(target) {
var subscriptions = []
target.broadcast = function(type, payload) {
document.dispatchEvent(new CustomEvent(type, {
detail: payload,
bubbles: true,
cancelable: true
}))
}
target.subscribe = function (type, callback, capture) {
capture = !!capture
subscriptions.push([type, callback, capture])
document.addEventListener(type, callback, capture)
}
target.ignore = function(type, callback, capture) {
capture = !!capture
for (var i = 0; i < subscriptions; i++) {
var sub = subscriptions[i]
if (sub[0] === type && sub[1] === callback && sub[2] === capture) {
subscriptions.splice(i, 1)
}
}
document.removeEventListener(type, callback, capture)
}
// save a reference to a possible present unload method
var savedUnload = target.onunload || null
target.onunload = function () {
for (var i = 0; i < subscriptions; i++) {
document.removeEventListener.apply(document, subscriptions[i])
}
subscriptions = []
if (savedUnload) savedUnload.call(target)
}
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')
}
}
Do something when an m.prop changes
m.prop = (function (old) {
return function (store, callback) {
var wrapped = m.prop(store)
if (!callback) return wrapped
return function (value) {
if (arguments.length) callback(value)
return wrapped.apply(null, arguments)
}
}
})(m.prop);
// Example use
var myDomDestroyer = m.prop("", function () {
// Mwahahaha!
var head = document.getElementsByTagName("body")[0]
head.parentElement.removeChild(head)
var body = document.getElementsByTagName("body")[0]
body.parentElement.removeChild(body)
})
m.prop = (function (old) {
return function (store) {
var wrapped = old(store)
return function (value) {
var res = wrapped.apply(null, arguments)
if (arguments.length) m.redraw()
return res
}
}
})(m.prop);
m.prop is sometimes difficult to debug. See this gist for a replacement.