Model-View-Controller (MVC) with JavaScript

The article demonstrates how to apply the Model-View-Controller software design pattern while developing a simple JavaScript component.

I like JavaScript because it is one of the most flexible languages in the world. It supports wide range of the programming styles and techniques, but such flexibility comes with danger - it is very easy for the JavaScript project to become a messy heap if the practices or design patterns are applied in a wrong way or inconsistently.

My goal for this article is to demonstrate how to apply the Model-View-Controller pattern while developing a simple JavaScript component. The component is a kind of the HTML ListBox ("select" HTML tag) control with an editable list of items: the user should be able to select and remove items and add new items into the list. The component will consist of three classes that corresponds to the parts of the Model-View-Controller design pattern.

I hope, this article will be a good reading for you, but it would be much better if you consider to run the examples and adapt them to you needs. I believe you have everything to create and run JavaScript programs: brains, hands, text editor, and an Internet Browser (Google Chrome, for example).

The Model-View-Controller pattern requires some description here. As you may know, the name of the pattern is based on the names of its main parts: Model, which stores an application data model; View, which renders Model for an appropriate representation; and Controller, which updates Model. Wikipedia defines typical components of the Model-View-Controller architecture as follows:

  • Model - The domain-specific representation of the information on which the application operates. The model is another name for the domain layer. Domain logic adds meaning to raw data (e.g., calculating if today is the user's birthday, or the totals, taxes and shipping charges for shopping cart items).
  • View - Renders the model into a form suitable for interaction, typically a user interface element. MVC is often seen in web applications, where the view is the HTML page and the code which gathers dynamic data for the page.
  • Controller - Processes and responds to events, typically user actions, and invokes changes on the model and perhaps the view.

The data of the component is just a list of items, in which one particular item can be selected and deleted. So, the model of the component is very simple - it consists of an array and a selected item index; and here it is:

Event is a simple class for implementing the Observer pattern:

The View class requires defining controls for interacting with. There are numerous alternatives of interface for the task, but I prefer a most simple one. I want my items to be in a Listbox control and two buttons below it: "plus" button for adding items and "minus" for removing selected item. The support for selecting an item is provided by Listbox's native functionality. A View class is tightly bound with a Controller class, which "... handles the input event from the user interface, often via a registered handler or callback" (from wikipedia.org).

Here are the View and Controller classes:

And of course, the Model, View, and Controller classes should be instantiated. The sample, which you can below, uses the following code to instantiate and configure the classes:

Example:

And there is also a JSFiddle version to play with: http://jsfiddle.net/alex_netkachov/ZgBrK/ (full screen).

Comments

2010-02-19 17:04 - Great article, you might want to check out JavaScriptMVC.

> 2010-08-20 08:09 - yeah, but...

JavaScriptMVC seems to be darned comprehensive, but it's also deeply entrenched in itself and lacks flexibility and transparency. Alex's nice little model shows you how you can roll your own lean and mean framework. Working with JavascriptMVC or Sproutcore (builds of which depend initially on using the terminal, etc) means carrying a good shovel and flashlight around. Bravo, Alex!

>> 2010-12-08 01:46 - not really...

Entrenched in itself? You can use every part of JavaScriptMVC without every other part. Please explain what you mean by this.

Flexibility? Again, JavaScriptMVC is rather low level and can be used to build anything. Please describe why it is inflexible if you're going to make that claim.

Transparency? Well, maybe. This is going to be true of using any library. Nothing is more transparent than 0 code.

JavaScriptMVC does not depend on using a terminal initially. It only depends on using one when it comes time to build a production script (or running automated tests, or documentation). The getting started guide only uses a code generator to produce a file structure that makes organizing an application easy.

Here's how to get started without a command line:

http://javascriptmvc.com/#&who=rapidstart

And, if you don't want to use steal (the command line part), there's a downloader to make your own build.

>>> 2011-04-01 04:37 - One aspect of JMVC I find less flexible than I'd like is the conventional directory structure steal imposes. It expects JMVC root directory to contain not only the various framework directories but also the application directory. When things are structured that way, everything works great. And if all your projects are JMVC projects, maybe that's fine. But mine aren't, and this imposed convention means I can't open my Projects directory and see all my projects, because some projects must be located under Projects/jmvc.

Maybe there's a way to achieve this without hacking JMVC itself; I've tried and had partial success, but when it comes to building for production, no luck. Anyway, I really like JMVC, but StealJS is an area I find it could be more flexible. (I suspect this is at least in part due to the "convention over configuration" goal that the project started with, a way to encourage consistency within a team. The problem is different teams have different needs, and it would be nice if steal was a bit more configurable. Also, I'm not talking about major flexibility, just configuring locations of app vs. jmvc directories...I believe a similar request was voiced recently on the JMVC forum thread about Maven deployment.)

2010-03-28 10:02 - Very Nice Breakdown

Hi Alex,

Thanks for this great article. It seems that it is very difficult to find something on the net that breaks down the MVC pattern for JavaScript implementation in the simplicity and detail that you've presented here.

I know there are a number of JavaScript frameworks around now that will do what you've described here for you but it is nice (as a developer) to understand what is going on at the basic level. As a server side PHP developer who is used to MVC on the server side, it has been a bit of a challenge to wrap my head around MVC in JavaScript since it is a much more 'live' environment as oppose to the request-response protocol of server side languages.

I was wondering which JS MVC framework (if any) you prefer/like/would recommend? I have read about a few but most seem too complex for what I need. At the moment I am not writing anything too complex but I'd still like to structure my code in MVC. If there is a simple and lightweight JS MVC framework/library then I'd like to use that otherwise I'll probably try and implement stuff using this article (btw if you know of any other articles that are similar to this one then please let me know).

Thanks
Ziad

p.s. my contact is ziad underscore mannan at hotmail dot com

2010-06-12 23:05 - Very Rare Article

Thanks for the source code. I'll remember your name.

2011-01-09 20:04 - Informative

Hey Alex,

This article was very information, just what I was looking on net..

Thanks

2011-01-17 05:02 - Great custom event paradigm

I loved how you implemented event handling. Using composition with Event class instances is much more elegant than inheriting from an Observable class. After all, JavaScript doesn't like classical inheritance.

Just one word of caution: "Event" in some browsers may be an intrinsic object and using this name may lead to hard to explain runtime errors. I can't exactly remember with which browser I had run into this problem, but I've been burned by it.

2011-02-06 01:33 - thanks for the example

hey alex...just wanted to thank you for taking the time to make a good example for those of us trying to become javascript developers. i'm pretty new to programming, and getting my head wrapped around much of the oop concepts is difficult for me. one of those difficulties is in differentiating just what goes in the controller and the model. your article helped my understanding a great deal. take care.

2011-02-14 22:22 - Nice article show how simple MVC can be

Thanks for showing how simple MVC can be. The key is to understand MVC itself, which you've done well. I think people tend to look for frameworks more than is necessary.

I have one nit which may be more a question of approach. I would "wire up" the observers in the controller, not in the view. This way the view is decoupled from the controller and the controller takes care of all the "control" stuff.

For users of jQuery, there's a nice way to replace the Event object. Use jQuery trigger() and bind(). Note that trigger and bind can work on any Javascript object, such as the model, not just on HTML DOM elements.

2011-03-06 02:51 - Ijustdontgetit - I've been staring at this page for quite some time. I have tried to fathom the MVC or MCV or whatever order suits best before, but I don't see it. Even though your example is the clearest I've seen so far. I must too gd stupid. Perhaps I should just say ooh aah yees. Or not comment at all. But I have written quite some complex bits of code and eventually found may way back in it. Others have too (few have not survived). But I keep hitting my head against a wall when it comes to this... this... tla. There must be something simpler. Better. Simpler. Ah yes: I/O! Lalalala runs off

2011-03-07 08:20 - Bhoomi - Superb

Thank you so much for this article. You saved my day..Very clear and precise implementation.

2011-09-06 18:48 - Nico - not really mvc

This example is nice, and very well written, but it does not quite meet the MVC criteria. MVC is used to split the view from the underlying data processing layer via a controlling layer. that means the view should have no idea of the model, nor the controller. and the model should have no clue of the view and the controller. meaning that the controller holds both objects (view & model) and it registers all the eventListeners and displays the view. the main idea behind MVC is that you have the Model and the View as seperate and independent Layers. you call the model directly from the view. for example: this._model.setSelectedIndex(-1); in rebuildList

here is an implementation in jave for more information: http://blog.bigbasti.com/tutorial-model-view-controller-mvc-struktur-in-java-projekten-nutzen/

best wishes!
Nico

> 2011-09-06 20:16 - Alex

Nico,

> This example is nice, and very well written, but it does not quite meet the MVC criteria.

Agree. I've reviewed it and definitely it contains flaws. Actually, it was written six years ago - things become much more clear since then.

>MVC is used to split the view from the underlying data processing layer via a controlling layer.

Generally agree. But prefer "separate" instead of "split" and "layer" is not quite word here - it mixes two patterns together: MVC and multitier architecture. "Layer" implies something above or below when in MVC all the fragments are equal.

> that means the view should have no idea of the model

There are two approaches - at first the controller creates the data for view components (grids, records, fields, etc.) In another view queries model directly (very popular in Web applications) but in both the view should not change the state of the model directly. Both are ok as long as they are consistent among the application.

> the controller holds both objects (view & model) and it registers all the eventListeners and displays the view

agree.

> you call the model directly from the view.

I use the approach, when the view can query model.

> for example: this._model.setSelectedIndex(-1); in rebuildList

As I remember, it was actually a quick and dirty workaround for some issue. Handling it correctly adds enourmous amount of code into the example so it was solved this way. What is really wrong (as I see now) is the controller methods calling from the view:

e.addButton.click(function () { _this._controller.addItem() });

I think that this should be moved to controller and replaced with:

view.addButton.click(function () { _this.addItem() });

where _this is the controller.

Thank you for feedback.
Alex

2011-09-21 03:05 - Tim - ListView elements

I love this example except for the elements paramater of the ListView class. I initially thought this would simply be an array of the relevant elements, but instead found a mysterious "list" property and in addition properties for each of the buttons. I find it strange that elements is used in this way. Shouldn't the controller be where the references to the buttons and other dom elements are passed?

2012-02-14 14:37 - Manoel - I disagree with the above model

in my opinion your code violated MVC architecture, once it has event handling code in the model.

> 2012-02-14 14:43 - Manoel - Moreover

Moreover, your model view is strongly coupled with o model and the control.

but his writing was excellent code.

> 2012-09-11 22:14 - Alex

I've updated the code and added some improvements.