Using Dojo’s dijit widgets for simple controller/view layers

Tags:

More complex JavaScript applications benefit from the MVC pattern just like other sorts of applications. Just like for other sorts of applications, there are dedicated MVC libraries for JavaScript, such as JavaScriptMVC.

Dojo, in my opinion one of the most powerful and flexible JS libraries, can be easily adapted to provide a reasonably well working MVC scheme, so why use a separate library?

MVC in Dojo

Dojo does not provide “obvious” MVC building blocks out of the box, but if we look a little deeper, it already has a lot we can use:

  • Dijit._Templated as view
  • Dijit widget or separate class as controller

As for the M, the model, we could use dojo.data or some custom classes. However for this post we’ll just look at the controller and view.

Depending on how complex we want to go, we can either use a single dijit widget as the controller and its template as the view, or we can use the dijit + template as the view and a separate class as a controller. Either way, we’ll achieve some nice separation of concerns.

Dijit._Widget as controller

Let’s first look at using just a dijit with no additional classes.

This is relatively straightforward, as we can easily refer parts of the view in the dijit by using dojoAttachPoint, dojoAttachEvent etc. in the template.

Here’s a simple controller stub, which in a typical Dojo setup would go into js/cu/ExampleController.js:

dojo.provide('cu.ExampleController');
 
dojo.require('dijit._Widget');
dojo.require('dijit._Templated');
 
dojo.declare('cu.ExampleController', [dijit._Widget, dijit._Templated], {
    templatePath: dojo.moduleUrl('cu.templates', 'Example.html'),
 
    activate: function(args) { },
    deactivate: function() { }
});

In this basic code snippet, we create a very simple dijit widget with two methods: activate and deactivate. The templatePath property is used to tell dijit where the template file for it is located, and for it we use the dojo.moduleUrl function, so that we don’t need to concern ourselves with the URLs more than needed.

What are the two methods? You usually might want a way to tell the controller when it’s being activated in your application and also when it’s being deactivated.

A Dijit template for the view

To pair with our controller Dijit, we need the template to be our view.

For this, we’ll just use a standard dijit template, as shown before:

<div>
    Hello, <span dojoAttachPoint="name"></span>
</div>

We can use all features of dijit._Templated in this template, but I kept it simple for this example.

This template file would usually go into js/cu/templates/Example.html so the URL generated in our controller is correct.

Thanks to dijit, we can easily put things into our view from the controller. For example, if we wanted to set the value of the span, we can simply write this.name.innerHTML = 'Foo'; in a method in the controller. Similarly, if we wanted to have certain actions happen when a button is pressed in the view, we can use dojoAttachEvent to attach an event handler function from the controller to the button’s click event.

Separate controller class

To achieve more separation, you may wish to include a third piece in the puzzle to act as the controller instead of the dijit.

Why would you want to have a third class making things more complex?

A good reason to do this would be if you wanted to abstract the interface of the view more. In our simple case, if we wanted to set the name in the view we used innerHTML to set it. What if the name span is changed into an input box? In this case our code would no longer work.

If we had abstracted our view, we might have a function such as view.setName('foo'), which would make our controller less coupled to the specific view implementation.

Going from the simple setup to this three-piece setup is relatively simple:

  • Rename ExampleController to ExampleView
  • Add a new class to act as the controller

Conclusion

To use our awesome controller (or view if you opt for the three-piece setup), we can simply do something such as:

dojo.require('cu.ExampleController');
dojo.addOnLoad(function(){
    var controller = new cu.ExampleController();
    controller.placeAt(document.body, 'only');
});

Using Dojo to create a basic MVC system is pretty easy, as dijits are very flexible and make working with DOM a breeze.

To take this one step further, you could use dojox.dtl to allow for more powerful and flexible templating markup.

I bet you can’t do this so easily in jQuery. ;)

Next post about this topic:
Building a lightweight application framework around custom Dojo MVC