When I first got into Javascript, it wasn’t obvious to me how best to use the language to do a simple model-view-controller.

I’ve heard of backbone, spine, and some other javascript mvc frameworks, but I just wanted to start with something really simple. My friend Jonas came up with a good example showing how our thinking has evolved after building some stuff.

Option 1: Prototype

In the prototype method you define your functions using the javascript prototype construct and then make use of ‘this’ and ‘self’ to make sure you are calling your methods with the right javascript context.

This is how we first stared doing simple mvc.

FormModel_literal.js

var FormModel = function(){};

FormModel.prototype.getInputText = function(){
   return $('#inputtext').val();
};

FormModel.prototype.setInputText = function(value){
   $('#inputtext').val(value);
};

FormController_prototype.js

var FormController = function(pModel){

    this.model = pModel || new FormModel();
    
    this.fill_clicked = function(){
        this.model.setInputText('Hello World');
    };

    this.clear_clicked = function(){
        this.model.setInputText('');
    }
};

FormController.prototype.init = function(){

    var self = this;

    $('#fillbutton').click(function(){ self.fill_clicked(); });
    $('#clearbutton').click(function(){ self.clear_clicked(); });
};

FormController.prototype.getModel = function(){
    return this.model;
};

It’s nice. It works. You don’t need to worry about state (it’s all in the model). But you do need to watch context (this, that, and self) and it’s easy to get wrong if you aren’t careful.

Option 2: Literal method

In the literal method, you use the javascript literal construct to keep most internal methods private, and then only expose those you want publicly consumed in the return statement.

FormModel_literal.js

var FormModel = function(){

    function getInputText(){
       return $('#inputtext').val();
    }

    function setInputText(value){
       $('#inputtext').val(value);
    }

    return {
        getInputText : getInputText,
        setInputText : setInputText
    }
};

FormController_literal.js

var FormController = function(pModel){

    var model = pModel || new FormModel();

    function fill_clicked(){
        model.setInputText('Hello World');
    }

    function clear_clicked(){
        model.setInputText('');
    }

    function init(){

        $('#fillbutton').click(function(){ fill_clicked(); });
        $('#clearbutton').click(function(){ clear_clicked(); });
    }

    return {
        init: init,
        model : model
    };
};

I think it’s elegant and nice. And I didn’t even know you could use a return statement like that in Javascript.

The advantage of this method is you don’t have to worry so much about getting the context wrong (this, that and self) as it’s all in the same context.

And it’s just easier on the eyes for me as it more closely resembles the classical OO model I am used to in Java and C#.

You can hook these up in view a test page as follows:

<html>

    <head>
        <script type="text/javascript" src="jquery-1.6.1.min.js"></script>

        <!-- Using function returning an Object literal (my preference) -->
        <script type="text/javascript" src="js/controllers/FormController_literal.js"></script>
        <script type="text/javascript" src="js/models/FormModel_literal.js"></script>

        <!-- Using Prototype -->
        <!--<script type="text/javascript" src="js/controllers/FormController_prototype.js" ></script>-->
        <!--<script type="text/javascript" src="js/models/FormModel_prototype.js"></script>-->

        <script type="text/javascript">

            $(document).ready(function() {
                new FormController().init();
            });

        </script>

    </head>

    <body>
        <input type="text" id="inputtext" name="inputtext" value="" />
        <input type="button" id="fillbutton" value="Fill with Text"/>
        <input type="button" id="clearbutton" value="Clear"/>
    </body>

</html>

So while both methods will work, we are currently leaning towards option 2 (the literal method).

It just seems cleaner, less stuff to worry about, and it looks good. Of course being relatively new to hard core javascript, and still looking for better ways, we reserve the right to change our minds tomorrow.

If you have any tips, better ideas, or feedback, we’d love to hear them.

Update:
Nice write up along similar lines from Ola Bini.

Advertisement