## Getting Started ### What is Mithril? Mithril is a client-side Javascript MVC framework, i.e. it's a tool to make application code divided into a data layer (called **M**odel), a UI layer (called **V**iew), and a glue layer (called **C**ontroller) Mithril is around 7.8 kB gzipped thanks to its [small, focused, API](mithril.md). It provides a templating engine with a virtual DOM diff implementation for performant rendering, utilities for high-level modelling via functional composition, as well as support for routing and componentization. The goal of the framework is to make application code discoverable, readable and maintainable, and hopefully help you become an even better developer. Unlike some frameworks, Mithril tries very hard to avoid locking you into a web of dependencies: you can use as *little* of the framework as you need. However, using its entire toolset idiomatically can bring lots of benefits: learning to use functional programming in real world scenarios and solidifying good coding practices for OOP and MVC are just some of them. --- ## A Simple Application Once you have a [copy of Mithril](installation.md), getting started is surprisingly boilerplate-free: ```markup Todo app ``` Yes, this is valid HTML 5! According to the specs, the `` and `` tags can be omitted, but their respective DOM elements will still be there implicitly when a browser renders that markup. --- ### Model In Mithril, an application typically lives in a namespace and contains components. Components are merely structures that represent a viewable "page" or a part of a page. In addition, an application can be organizationally divided into three major layers: Model, Controller and View. For simplicity, our application will have only one component, and we're going to use it as the namespace for our application. In Mithril, a *component* is an object that contains a `view` function and optionally a `controller` function. ``` //an empty Mithril component var myComponent = { controller: function() {}, view: function() {} } ``` In addition to holding a controller and a view, a component can also be used to store data that pertains to it. Let's create a component. ```markup ``` Typically, model entities are reusable and live outside of components (e.g. `var User = ...`). In our example, since the whole application lives in one component, we're going to use the component as a namespace for our model entities. ```javascript var todo = {}; //for simplicity, we use this component to namespace the model classes //the Todo class has two properties todo.Todo = function(data) { this.description = m.prop(data.description); this.done = m.prop(false); }; //the TodoList class is a list of Todo's todo.TodoList = Array; ``` [`m.prop`](mithril.prop.md) is simply a factory for a getter-setter function. Getter-setters work like this: ```javascript //define a getter-setter with initial value `John` var a_name = m.prop("John"); //read the value var a = a_name(); //a == "John" //set the value to `Mary` a_name("Mary"); //Mary //read the value var b = a_name(); //b == "Mary" ``` Note that the `Todo` and `TodoList` classes we defined above are plain vanilla Javascript constructors. They can be initialized and used like this: ```javascript var myTask = new todo.Todo({description: "Write code"}); //read the description myTask.description(); //Write code //is it done? var isDone = myTask.done(); //isDone == false //mark as done myTask.done(true); //true //now it's done isDone = myTask.done(); //isDone == true ``` The `TodoList` class is simply an alias of the native `Array` class. ```javascript var list = new todo.TodoList(); list.length; //0 ``` According to the classic definition of the MVC pattern, the model layer is responsible for data storage, state management and business logic. You can see that our classes above fit the criteria: they have all the methods and properties that they need to be assembled into a meaningful state. A `Todo` can be instantiated, and have its properties changed. The list can have todo items added to it via the `push` method. And so on. #### View-Model Our next step is to write a view-model that will use our model classes. A view-model is a model level entity that stores UI state. In many frameworks UI state is typically stored in a controller, but doing so makes the code harder to scale since controllers aren't designed to be data providers. In Mithril, UI state is understood to be model data, even though it doesn't necessarily map to a database ORM entity. View-models are also responsible for handling business logic that revolves around UI-specific restrictions. For example a form might have an input and a cancel button. In such a case, it's the view-model's responsibility to track the current state of the input vs the original state and to apply a cancellation, if required. In the event the form was saved, then view-model would delegate saving to a more appropriate ORM model entity. In the case of our todo application, the view-model needs a few things: it needs to track a running list of todos and a field for adding new todos, and it needs to handle the logic of adding to the todo and the implications of this action of the UI. ```javascript //define the view-model todo.vm = { init: function() { //a running list of todos todo.vm.list = new todo.TodoList(); //a slot to store the name of a new todo before it is created todo.vm.description = m.prop(''); //adds a todo to the list, and clears the description field for user convenience todo.vm.add = function(description) { if (description()) { todo.vm.list.push(new todo.Todo({description: description()})); todo.vm.description(""); } }; } }; ``` The code above defines a view-model object called `vm`. It is simply a javascript object that has an `init` function. This function initializes the `vm` object with three members: `list`, which is simply an array, `description`, which is an `m.prop` getter-setter function with an empty string as the initial value, and `add`, which is a method that adds a new Todo instance to `list` if an input description getter-setter is not an empty string. Later in this guide, we'll pass the `description` property as the parameter to this function. When we get there, I'll explain why we're passing description as an argument instead of simply using OOP-style member association. You can use the view-model like this: ```javascript //initialize our view-model todo.vm.init(); todo.vm.description(); //[empty string] //try adding a to-do todo.vm.add(todo.vm.description); todo.vm.list.length; //0, because you can't add a to-do with an empty description //add it properly todo.vm.description("Write code"); todo.vm.add(todo.vm.description); todo.vm.list.length; //1 ``` --- ### Controller In classic MVC, the role of the controller is to dispatch actions from the view to the model layer. In traditional server-side frameworks, the controller layer is of large significance because the nature of HTTP requests, responses and the framework abstractions that are exposed to developers require that the controller act as an adapter layer to transform the serialized data from HTTP requests to something that can be passed to ORM model methods. In client-side MVC, however, this dissonance doesn't exist, and controllers can be extremely simple. Mithril controllers can be stripped down to a bare minimum, so that they only perform a single essential role: to expose a scoped set of model-level functionality. As you may recall, models are responsible for encapsulating business logic, and view-models encapsulate logic that pertains specifically to UI state, so there's really nothing else for a controller to abstract away, and all it needs to do is expose a slice of the model layer that pertains to the UI that is currently in view. In other words, all our controller needs to do is this: ```javascript todo.controller = function() { todo.vm.init() } ``` --- ### View The next step is to write a view so users can interact with the application. In Mithril, views are plain Javascript. This comes with several benefits (proper error reporting, proper lexical scoping, etc.), while still allowing [HTML syntax to be used via a preprocessor tool](https://github.com/insin/msx) ```javascript todo.view = function() { return m("html", [ m("body", [ m("input"), m("button", "Add"), m("table", [ m("tr", [ m("td", [ m("input[type=checkbox]") ]), m("td", "task description"), ]) ]) ]) ]); }; ``` The utility method `m()` creates virtual DOM elements. As you can see, you can use CSS selectors to specify attributes. You can also use the `.` syntax to add CSS classes and the `#` to add an id. In fact, when not using the [MSX](https://github.com/insin/msx) HTML syntax preprocessor, it's recommended that you embrace using CSS selectors (e.g. `m(".modal-body")`) to really benefit from their inherent semantic expressiveness. For the purposes of testing out our code so far, the view can be rendered using the `m.render` method: ```javascript m.render(document, todo.view()); ``` Notice that we pass a root DOM element to attach our template to, as well as the template itself. This renders the following markup: ```markup
task description
``` Note that `m.render` is a very low level method in Mithril that draws only once and doesn't attempt to run the auto-redrawing system. In order to enable auto-redrawing, the `todo` component must be initialized by either calling `m.mount` or by creating a route definition with `m.route`. Also note that, unlike observable-based frameworks like Knockout.js, setting a value in a `m.prop` getter-setter does NOT trigger redrawing side-effects in Mithril. --- #### Data Bindings Let's implement a **data binding** on the text input. Data bindings connect a DOM element to a Javascript variable so that updating one updates the other. ```javascript //binding a model value to an input in a template m("input", {value: todo.vm.description()}) ``` This binds the `description` getter-setter to the text input. Updating the value of the description in the model updates the DOM input when Mithril redraws. ```javascript todo.vm.init(); todo.vm.description(); // empty string m.render(document, todo.view()); // input is blank todo.vm.description("Write code"); //set the description in the controller m.render(document, todo.view()); // input now says "Write code" ``` At a glance it may seem like we're doing something very expensive by redrawing, but as it turns out, calling the `todo.view` method multiple times does not actually re-render the entire template. Internally, Mithril keeps a virtual representation of the DOM in cache, scans for changes, and then only modifies the absolute minimum required to apply the change to the DOM. In practice, this results in surprisingly fast re-rendering. In the case above, Mithril only touches the `value` attribute of the input. Note that the example above only *sets* the value of the input element in the DOM, but it never *reads* it. This means that typing something on the input and then re-rendering will clobber the text on screen. --- Fortunately, bindings can also be **bi-directional**: that is, they can be coded in such a way that, in addition to setting the DOM value, it's also possible to read it as a user types, and then update the `description` getter-setter in the view-model. Here's the most basic way of implementing the view-to-model part of the binding: ```javascript m("input", {onchange: m.withAttr("value", todo.vm.description), value: todo.vm.description()}) ``` The code bound to the `onchange` can be read like this: "with the attribute value, set todo.vm.description". Note that Mithril does not prescribe how the binding updates: you can bind it to `onchange`, `onkeypress`, `oninput`, `onblur` or any other event that you prefer. You can also specify what attribute to bind. This means that just as you are able to bind the `value` attribute in an `