npm i -D mithril-template
var mithrilTemplate = require("mithril-template")
console.log(mithrilTemplate('<h1 class="greetings">Hello World</h1>'))
The most basic form of data binding is text interpolation using the “Mustache” syntax (double curly braces):
<div class="greeting">
Hello {{ name }}!
</div>
that will output:
m(".greeting","Hello "+name+"!")
Awesome, right? So let's dive deeper.
Interpolations can't be used within html tag definiition (also in attributes), so this code is invalid:
<div key="{{ foo }}" class="bar">
Hello World!
</div>
instead use a binding attribute:
<div :key="foo" class="bar">
Hello World!
</div>
output:
m(".bar",{key:foo},"Hello World!")
Note that {
and }
characters are reserved in templates for interpolation, so if you have to write them use this workaround:
<span>This is how to use {{ "{" }} and {{ "}"+"}" }} chars.</span>
You can't use {
and }
html entities because mithril will escape them
To embed component, his name must end on -component
, be kebab-case (a.k.a. snake-case) that will be automatically converted to camelCase and can't be self-closed tag:
<custom-component></custom-component>
output:
m(customComponent)
Attributes that are not followed by :
(colon) will be ommited.
<custom-component class="custom-class"></custom-component>
output:
m(customComponent)
so if you want to pass data into component use binding syntax instead:
<custom-component :class="'custom-class'"></custom-component>
output:
m(customComponent,{class:'custom-class'})
You can nest anything inside the component:
<custom-component :key="'unique420'">
<span style="color: red;">Hello!</span>
</custom-component>
output:
m(customComponent,{key:'unique420'},m("span[style='color: red;']","Hello!"))
Nested data will be available in vnode.children
component view property:
<!--customComponent view-->
<div class="styled-message">{{ vnode.children }}</div>
output:
m(".styled-message",vnode.children)
You probably noticed that html attributes are compiled to hardcoded selectors:
<input type="text" name="name" value="name">
output:
m("input[type=text][name=name][value=name]")
if you want to bind html attribute just put :
(colon) before attribute name:
<input type="text" name="name" :value="name">
output:
m("input[type=text][name=name]",{value:name})
you can also bind events and lifecycle hooks:
<div :oninit="initialize" :onclick="doSomething">
Hello World!
</div>
output:
m("div",{oninit:initialize,onclick:doSomething},"Hello World!")
Directives are putted as html attributes that are previxed by *
(asterisk).
The result hyperscript code will be surrounded by javascript flow statements.
There are four available directives, that can be mixed togheder:
for
if
elseif
else
Let's explain, but note that examples' outputs below are unminified, for better readability.
usage:
<div class="foo" *if="varr % 2 == 0">
odd
</div>
output:
varr % 2 == 0
? m(".foo","odd")
: ""
<div class="foo" *if="varr % 2 == 0">
odd
</div>
<div *elseif="varr % 5 == 0">
divisible by 5
</div>
<div *else>
other
</div>
output:
[
varr % 2 == 0
? m(".foo","odd")
: varr % 5 == 0
? m("div","divisible by 5")
: m("div","other")
]
<ul>
<li *for="item in items">
{{ item.name }}
</li>
</ul>
output:
m("ul", items.map(function(n){
return m("li", n.name)
}))
<ul>
<li *for="item, index in items">
#{{ index }}: {{ item.name }}
</li>
</ul>
output:
m("ul", items.map(function(n, a){
return m("li","#"+a+": "+n.name)
}))
for loop can be used with else (or elseif) statement:
<ul>
<li *for="item, index in items">
#{{ index }}: {{ item.name }}
</li>
<li *else>
items not found
</li>
</ul>
output:
m("ul", items.length
? items.map(function(n, t){
return m("li","#"+t+": "+n.name)
})
: m("li","items not found")
)
so if items array is empty (loop won't execute even once) then else statement will be executed
To maximally compress output- whitespaces whose belongs to tags are not properly handled, so if you write this code:
foo <span>bar</span> baz qux
the transpiled code will be:
["foo",m("span","bar"),"baz qux"]
instead of:
["foo ",m("span","bar")," baz qux"]
that you may expected. So if you need space between text and tag do it by this workaround:
foo{{ " " }}<span>bar</span>{{ " " }}baz qux
- properly support splats for better minification
- produce maximally minified js code (also minify literal selectors)