< Previous | Next > | Table of Contents
In the 06 - Components lesson, we created the state management code for an
example with a conditions
component and two temperature components, temperature:air
and
temperature:water
.
In this section, we'll wire this up to Mithril.
First, we can use Mithril Stream as a stream library. For our
purposes, it works just like flyd
. The only difference is that you call m.stream()
instead of
flyd.stream()
, and m.stream.scan
instead of flyd.scan
.
Next, remember that we had an actions
object and a states
stream:
var actions = app.Actions(update);
states.map(function(state) {
document.write("<pre>" + JSON.stringify(state, null, 2) + "</pre>");
});
Now, we'll use m.mount
and a minimal Mithril component to render the view. We'll pass the
actions
and state
attributes to a top-level App
component:
m.mount(document.getElementById("app"), {
view: () => m(App, { state: states(), actions })
});
We are calling states()
to get the latest from the stream and pass it as the state
attribute.
With Mithril's auto-redraw system, the view is automatically re-rendered after user interaction.
The App
component retrieves state
and actions
from the passed-in attributes. We pass these on
to other components, in this case Conditions
and Temperature
. Notice that we have two instances
of Temperature
, and we pass a different id
to each one.
var App = {
view: function(vnode) {
var { state, actions } = vnode.attrs;
return m("div",
m(Conditions, { state, id: "conditions", actions }),
m(Temperature, { state, id: "temperature:air", actions }),
m(Temperature, { state, id: "temperature:water", actions }),
m("pre", JSON.stringify(state, null, 4))
);
}
};
The Conditions
component displays a checkbox for "precipitations" and a series of radio butons for
the sky (Sunny, Cloudy, Mix of sun/clouds). The state
is used to reflect the current state, and
actions
are called to update the state when the user changes the checkbox and radio buttons:
var skyOption = function({ state, id, actions, value, label }) {
return m("label",
m("input", { type: "radio", id: value, name: "sky",
value, checked: state[id].sky === value,
onchange: evt => actions.changeSky(id, evt.target.value)
}),
label
);
};
var Conditions = {
view: function(vnode) {
var { state, id, actions } = vnode.attrs;
return m("div",
m("label",
m("input", {
type: "checkbox",
checked: state[id].precipitations,
onchange: evt =>
actions.togglePrecipitations(id, evt.target.checked)
}),
"Precipitations"
),
m("div",
skyOption({ state, id, actions, value: "SUNNY",
label: "Sunny"}),
skyOption({ state, id, actions, value: "CLOUDY",
label: "Cloudy"}),
skyOption({ state, id, actions, value: "MIX",
label: "Mix of sun/clouds"})
)
);
}
};
The Temperature
component is similar:
var Temperature = {
view: function(vnode) {
var { state, id, actions } = vnode.attrs;
return m("div",
state[id].label, " Temperature: ",
state[id].value, m.trust("°"), state[id].units,
m("div",
m("button",
{ onclick: () => actions.increment(id, 1) },
"Increment"),
m("button",
{ onclick: () => actions.increment(id,-1) },
"Decrement")
),
m("div",
m("button",
{ onclick: () => actions.changeUnits(id) },
"Change Units")
)
);
}
};
You can see the complete example below.
We can wire up Meiosis to Mithril using m.mount
and passing state
from the latest value of the
states
stream, along with actions
, to the top-level Mithril component.
Then, all Mithril components in the application are consistent: they all receive state
and
actions
. When rendering other components, state
and actions
are passed along. When a component
is used multiple times, or when you want to define the state property outside of the component, you
also pass the id
.
Components can then use the state
to render the view according to the current application state,
and call actions
to trigger changes. Because of Mithril's
auto-redraw system, the view is automatically re-rendered.
Of course, if you trigger state changes outside of Mithril's auto-redraw (see When Mithril does not
redraw) you have to call
m.redraw()
yourself.
This concludes the Meiosis tutorial. See 11 - What's Next? for ideas on where to go from here.
< Previous | Next > | Table of Contents
Meiosis is developed by @foxdonut00 / foxdonut and is released under the MIT license.