A Walk-through of a Simple JavaScript MVC Implementation

I’ve used versions of this in the past when the use case was appropriate, and loading a full featured library/framework would be overkill.

Despite being written in ES6 (well, mostly), I’ve broken this out using the Module Pattern to make it easier to walk thought, and because the pattern doesn’t require any tooling, just some concatenation to run in the browser. If you’d like to know more about that pattern, I have a slide deck on the Module Pattern and related concepts.

Hopefully this will demystify the the “magic” of the MVC Pattern. The first module we’ll look at is the Event module.

The Event Module

This implements a simple Observer Pattern, although it does not strictly adhere to, or complete, the pattern. This event code should be private within simpleMVC, but because of my use of the Module Pattern and breaking it all into separate chunks, it can’t be, so I’ve called it _Event to denote that it’s private (as I have with various private properties)

The constructor (here just the function definition) defines some basic properties.

Event has two methods:

  • attach(listener) which simply adds an observer to the list of observers
  • notify(args) which allows the subject to notify its observers
simpleMVC.Event.js

The Model Module

The model controls getting the data, setting/changing the data and subsequently notifying observers that it has changed. Also, because this is simple, the Model stores data only during runtime (this._data ), there’s no database or backend connection code.

The constructor creates a basic property, and another is set to a new instance of _Event (the Observer pattern from above).

Model has two methods:

  • get() which returns the data
  • set() which sets the data, and notifies the observers
simpleMVC.Model.js

The Views

Theses views take simple to an absolute minimalism. They don’t support a render function, templating, or building of DOM elements.

Despite a lot of duplicate code, I’ve created individual One-Way and Two-Way views modules, because simple

The One-Way View

Supports only one-way binding.

The constructor sets a couple basic properties, and defines the observer function.

This view has only one method:

  • show() which updates the DOM
simpleMVC.OneWayView.js

The Two-Way View

Not surprisingly, it supports two-way binding.

The constructor here is most complicated, it:

  • sets a couple basic properties
  • defines the observer function ( onSet() )
  • and unlike the One-Way, a property is set to a new instance of _Event which is used as the callback from the DOM’s .addEventListener method

This view has only one method, same as One-Way’s:

  • show() which updates the DOM
simpleMVC.TwoWayView.js

The Controller

The Controller sits between the View and Model, linking it all together, and takes care of user changes or manipulation.

The constructor defines a couple basic properties, and checks if the view is a Two-Way (it has an .onChanged method) and if so establishes a subject’s observer.

It defines one method:

  • update(data) which calls set() on the Model.
simpleMVC.Controller.js

Using simpleMVC

That’s all for simpleMVC “framework”, so to put it all together, here’s a sample main function. It defines two views of a single model: one a one-way, and the other a two-way. After a 4 second timeout, it updates the model, and you can see the change on-screen. The user can also update the model via the two-way view’s input tag.

/**
* main
*/
var main = function() {
var model = new simpleMVC.Model(12), // 12 is initial value

aView = new simpleMVC.TwoWayView(model, document.getElementById('points-a')),
aController = new simpleMVC.Controller(model, aView),

bView = new simpleMVC.OneWayView(model, document.getElementById('points-b')),
bController = new simpleMVC.Controller(model, bView);
// these are for initial show, if not shown some other way
aView.show();
bView.show();

// example of changing the model directly
window.setTimeout(
() => model.set(20),
4000
);

};

And the sample html:

<div>A: <input id="points-a"></input><div>
<div>B: <span id="points-b"></span></div>

You can see it in action on CodePen http://codepen.io/toddzebert/pen/yOZKMK

It’s worth noting that this code has no sanity checks, no error handling, no clean up of object so memory leaks could occur, etc that would make it production ready.

Thanks for reading!