# learn-elm-architecture-in-javascript
**Repository Path**: mirrors_dwyl/learn-elm-architecture-in-javascript
## Basic Information
- **Project Name**: learn-elm-architecture-in-javascript
- **Description**: :unicorn: Learn how to build web apps using the Elm Architecture in "vanilla" JavaScript (step-by-step TDD tutorial)!
- **Primary Language**: Unknown
- **License**: GPL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2020-08-08
- **Last Updated**: 2026-01-24
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# Learn Elm Architecture in _Plain_ JavaScript
Learn how to build web applications using
the Elm ("Model Update View") Architecture in "_plain_" JavaScript.
[](https://travis-ci.org/dwyl/learn-elm-architecture-in-javascript)
[](https://codecov.io/gh/dwyl/learn-elm-architecture-in-javascript)
[](https://david-dm.org/dwyl/learn-elm-architecture-in-javascript)
[](https://david-dm.org/dwyl/learn-elm-architecture-in-javascript?type=dev)
[](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
[](http://hits.dwyl.io/dwyl/learn-elm-architecture-in-javascript)
> We think Elm is the _future_ of Front End Web Development
for all the _reasons_ described in:
[github.com/dwyl/**learn-elm#why**](https://github.com/dwyl/learn-elm#why)
_However_ we _acknowledge_ that Elm is "_**not everyone's taste**_"!
> What [_many_](https://youtu.be/VNGFep6rncY)
Front-End Developers _are_ learning/using is
[React.js](https://github.com/dwyl/learn-react).
_Most_ new _React.js_ apps are built using
[Redux](https://github.com/dwyl/learn-redux) which "_takes cues from_"
(_takes **all** it's **best ideas/features** from_) Elm:

> Therefore, by learning the Elm Architecture,
you will **_intrinsically_ understand Redux**
which will help you learn/develop
[React](https://github.com/dwyl/learn-react/issues/18)
apps.
> This ***step-by-step tutorial*** is a _gentle_ introduction to
the Elm Architecture,
for people who write JavaScript and want
a _**functional**, **elegant** and **fast**_
way of organizing their JavaScript code _without_
having the learning curve
of a completely new (_functional_) programming language!
## _Why?_

_Organizing_ `code` in a Web (_or Mobile_) Application
is _really easy_ to ***over-complicate***,
_especially_ when you are just starting out and there
are _dozens_ of competing ideas
all _claiming_ to be the "***right way***"...
When we encounter this type of "_what is the **right way**_?"
question,
we always follow
[***Occam's Razor***](https://en.wikipedia.org/wiki/Occam%27s_razor)
and _ask_:
what is the ***simplest way***?
In the case of web application organization,
the ***answer*** is:
the "**Elm _Architecture_**".
When compared to _other_ ways of organizing your code,
"Model Update View" (MUV) has the following benefits:
+ Easier to _understand_ what is going on in more advanced apps because there is no complex logic,
only one basic principal
and the "_flow_" is _always_ the same.
+ ***Uni-directional data flow*** means the "state"
of the app is always _predictable_;
given a specific starting "state" and sequence of update actions,
the output/end state will _always_ be the same. This makes testing/testability
very easy!
+ There's **no** "***middle man***" to complicate things
(_the way there is in other application architectures
such as
[Model-view-Presenter](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter) or "Model-View-ViewModel" (MVVM) which is "overkill" for most apps_).
> _**Note**: **don't panic** if any of the terms above are strange
or even confusing to you right now.
> Our **quest** is to put all the concepts into **context**.
> And if you get "**stuck**" at any point, we are here to help!
> Simply **open a question** on GitHub:_
[github.com/dwyl/**learn-elm-architecture**-in-javascript/**issues**](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
## _Who? (Should I Read/Learn This...?)_
[](https://www.youtube.com/results?q=The+Korgis+-+Everybody%27s+Gotta+Learn+Sometime)
Anyone who knows a _little_ bit of JavaScript
and wants to learn how to organize/structure
their code/app in a _sane_, predictable and testable way.
### _Prerequisites_?
[](https://www.ted.com/talks/graham_hill_less_stuff_more_happiness)
+ **_Basic_ JavaScript Knowledge**.
see: [github.com/dwyl/**Javascript**-the-**Good-Parts**-notes](https://github.com/iteles/Javascript-the-Good-Parts-notes)
+ _Basic_ Understanding of **TDD**. If you are _completely_ new to TDD,
please see: [github.com/dwyl/**learn-tdd**](https://github.com/dwyl/learn-tdd)
+ A computer with a Web Browser.
+ **30 minutes**.
> No other knowledge is assumed or implied.
If you have **_any_ questions**, ***please ask***:
[github.com/dwyl/**learn-elm-architecture**-in-javascript/**issues**](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
## _What?_
[](https://youtu.be/yYCmhHFhopA?t=4s)
### A _Complete Beginner's_ Guide to "MUV"
Start with a few definitions:
+ **Model** - or "data model" is the place where all data is stored;
often referred to as the application's `state`.
+ **Update** - how the app handles `actions` performed
by people and `update`s the `state`,
usually organised as a `switch` with various `case` statements corresponding
to the different "_actions_" the user can take in your App.
+ **View** - what people using the app can _see_;
a way to `view` the Model (in the case of the first tutorial below,
the counter) as `HTML` rendered in a web browser.

If you're not into flow diagrams,
here is a much more "user friendly" explanation
of The Elm Architecture ("TEA"):

[**Kolja Wilcke**'s](https://twitter.com/01k/status/986528602635358208?s=20)
["View Theater" diagram](https://github.com/w0rm/creating-a-fun-game-with-elm/blob/001baf05b3879d12c0ff70075e9d25e8cc7c4656/assets/the-elm-architecture1.jpg)
Creative Commons License
[Attribution 4.0 International (CC BY 4.0)](https://twitter.com/01k/status/986528602635358208?s=20)
In the "View Theatre" diagram, the:
+ **`model`** is the ensamble of characters (_or "**puppets**"_)
+ **`update`** is the function that transforms (_"changes"_) the `model`
(_the "**puppeteer**"_).
+ **`view`** what the audience sees through "view port" (_stage_).
> If this diagram is not clear (_yet_), again, don't panic,
it will all be clarified when you start seeing it in _action_ (_below_)!
## _How?_
### 1. Clone this Repository
```sh
git clone https://github.com/dwyl/learn-elm-architecture-in-javascript.git && cd learn-elm-architecture-in-javascript
```
### 2. Open Example `.html` file in Web Browser
> **Tip**: if you have **node.js** installed, simply run **`npm install`**!
> That will install **`live-server`** which will _automatically_ refresh
your browser window when you make changes to the code!
(_makes developing faster!_)
When you open `examples/counter-basic/index.html` you should see:

Try clicking on the buttons to increase/decrease the counter.
### 3. Edit Some Code
In your Text Editor of choice,
edit the _initial value_ of the model
(_e.g: change the initial value from 0 to 9_).
Don't forget to save the file!

### 4. Refresh the Web Browser
When you refresh the your Web Browser you will see
that the "_initial state_" is now **9**
(or whichever number you changed the initial value to):

You have just seen how easy it is to set the "_initial state_"
in an App built with the Elm Architecture.
### 5. Read Through & Break Down the Code in the Example
You _may_ have taken the time to read the code in Step 3 (_above_) ...
If you did, _well done_ for challenging yourself
and getting a "_head start_" on reading/learning!
Reading (_other people's_) code is the _fastest_ way
to learn programming skills and
the _only_ way to learn useful "_patterns_".
If you didn't read through the code in Step 3, that's ok!
Let's walk through the functions _now_!
> As always, our _hope_ is that the functions
are clearly named and well-commented,
please inform us if anything is unclear please
ask any questions as **issues**:
[github.com/dwyl/**learn-elm-architecture**-in-javascript/**issues**](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
### 5.1 `mount` Function Walkthrough
The mount function "initializes" the app and tells the _view_
how to process a `signal` sent by the user/client.
```js
function mount(model, update, view, root_element_id) {
var root = document.getElementById(root_element_id); // root DOM element
function signal(action) { // signal function takes action
return function callback() { // and returns callback
model = update(model, action); // update model according to action
view(signal, model, root); // subsequent re-rendering
};
};
view(signal, model, root); // render initial model (once)
}
```
The `mount` function receives the following _four_ arguments:
+ `model`: "_initial state_" of your application
(_in this case the counter which starts at 0_)
+ `update`: the function that gets executed when ever a "_signal_"
is received from the client (_person using the app_).
+ `view`: the function that renders the DOM (_see: section 5.3 below_)
+ `root_element_id` is the `id` of the "root DOM element"; this is the DOM element
where your app will be "_mounted to_". In other words your app
will be _contained_ within this root element.
(_so make sure it is empty before `mount`ing_)
The first line in `mount` is to get a _reference_ to the root DOM element;
we do this _once_ in the entire application to _minimize_ DOM lookups.
#### `mount` > `signal` > `callback` ?
The _interesting_ part of the `mount` function is `signal` (_inner function_)!
At first this function may seem a little strange ...
_Why_ are we defining a function that returns another function?
If this your first time seeing this "_pattern_",
welcome to the wonderful world of "_closures_"!
#### _What_ is a "Closure" and _Why/How_ is it Useful?
A `closure` is an inner function that has access
to the outer (enclosing) function's variables—scope chain.
The closure has three scope chains: it has access to its own scope
(variables defined between its curly brackets), it has access to
the outer function's variables, and it has access to the global variables.
In the case of the `callback` function inside `signal`,
the `signal` is "passed" to the various bits of UI
and the `callback` gets executed when the UI gets interacted with.
If we did not have the `callback` the `signal`
would be executed _immediately_ when the `button` is _defined_.
Whereas we only want the `signal` (`callback`) to be triggered
when the button is _clicked_.
Try removing the `callback` to see the effect:

The `signal` is triggered when button is _created_, which _re-renders_
the `view` creating the button again. And, since the `view` renders _two_
buttons each time it creates a "_chain reaction_" which almost
instantly _exceeds_ the "***call stack***"
(_i.e. exhausts the allocated memory_) of the browser!
Putting the `callback` in a _closure_ means we can pass a _reference_
to the `signal` (_parent/outer_) function to the `view` function.
##### Further Reading on Closures
+ https://developer.mozilla.org/en/docs/Web/JavaScript/Closures
+ http://javascriptissexy.com/understand-javascript-closures-with-ease/
+ ... if closures aren't "clicking",
or you want _more_ detail/examples,
[***please ask***!](https://github.com/dwyl/learn-elm-architecture-in-javascript/issues)
#### 5.1.1 `mount` > render initial view
The last line in the `mount` function is to _render_ the `view` function
for the first time, passing in the `signal` function, initial model ("state")
and root element. This is the _initial_ rendering of the UI.
### 5.2 Define the "_Actions_" in your App
The next step in the Elm Architecture is to _define_ the Actions
that can be taken in your application. In the case of our _counter_
example we only have _two_ (_for now_):
```js
// Define the Component's Actions:
var Inc = 'inc'; // increment the counter
var Dec = 'dec'; // decrement the counter
```
These _Actions_ are used in the `switch` (_i.e. decide what to do_)
inside the `update` function.
Actions are always defined as a `String`.
The Action _variable_ gets passed around inside the JS code
but the `String` representation is what appears in the DOM
and then gets passed in `signal` from the UI back to the `update` function.
One of the biggest (_side_) benefits of defining actions like this
is that it's really quick to see what the application _does_
by _reading_ the list of actions!
### 5.3 Define the `update` Function
The `update` function is a simple
[`switch`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/switch)
statement that evaluates the `action` and "dispatches"
to the required function for processing.
In the case of our simple counter we aren't defining functions for each `case`:
```js
function update(model, action) { // Update function takes the current model
switch(action) { // and an action (String) runs a switch
case Inc: return model + 1; // add 1 to the model
case Dec: return model - 1; // subtract 1 from model
default: return model; // if no action, return current model.
} // (default action always returns current)
}
```
However if the "_handlers_" for each `action` were "_bigger_",
we would split them out into their own functions e.g:
```js
// define the handler function used when action is "inc"
function increment(model) {
return model + 1
}
// define handler for "dec" action
function decrement(model) {
return model - 1
}
function update(model, action) { // Update function takes the current state
switch(action) { // and an action (String) runs a switch
case Inc: return increment(model); // add 1 to the model
case Dec: return decrement(model); // subtract 1 from model
default: return model; // if no action, return current state.
} // (default action always returns current)
}
```
This is _functionally_ equivalent to the simpler `update` (_above_)
But does not offer any _advantage_ at this stage (_just remember it for later_).
### 5.4 Define the `view` Function
The `view` function is responsible
for _rendering_ the `state` to the DOM.
```js
function view(signal, model, root) {
empty(root); // clear root element before
[ // Store DOM nodes in an array
button('+', signal, Inc), // create button (defined below)
div('count', model), // show the "state" of the Model
button('-', signal, Dec) // button to decrement counter
].forEach(function(el){ root.appendChild(el) }); // forEach is ES5 so IE9+
}
```
The `view` receives three arguments:
+ `signal` defined above in `mount` tells each (DOM) element
how to "handle" the user input.
+ `model` a reference to the _current_ value of the counter.
+ `root` a reference to the root DOM element where the app is _mounted_.
The `view` function starts by _emptying_
the DOM inside the `root` element using the `empty` helper function.
This is _necessary_ because, in the Elm Architecture, we _re-render_
the _entire_ application for each action.
> See note on DOM Manipulation and "Virtual DOM" (_below_)
The `view` creates a _list_ (`Array`) of DOM nodes that need to be rendered.
#### 5.4.1 `view` helper functions: `empty`, `button` and `div`
The `view` makes use of three "helper" (_DOM manipulation_) functions:
1. `empty`: empty the `root` element of any "child" nodes.
_Essentially_ `delete` the DOM inside whichever element's passed into `empty`.
```js
function empty(node) {
while (node.firstChild) { // while there are still nodes inside the "parent"
node.removeChild(node.firstChild); // remove any children recursively
}
}
```
2. `button`: creates a
[`