Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web

Introduction to MVC in JavaScript

3.89/5 (8 votes)
1 Dec 2014CPOL5 min read 31K   56  
A very small Single Page App using normal JavaScript, jQuery, HTML (no framework)

MVC in JavaScript

In order to understand MVC in JavaScript, I will first explain briefly about MVC - what is the purpose of each component in MVC, how this pattern is becoming popular and how you can implement it using JavaScript? At the end of this article, I will be sharing one dummy example (task checker) that I made using MVC in JavaScript.

1. Model

It simply means data. Any datamember or any datastructure which will be used for storing data will be called model. Moreover, the way to insert/delete data or other methods used for performing different operations on data will be written in model only. For example, an employee object can have employee name, id, salary, work experience, etc. Here, employee object is a model since it is actual data.

2. View

It is that part of MVC which we see on screen. As the name suggests, View involves a User Interface that will be used for displaying data. This data will be taken from model. It means, every view object contains a model object. For example, a table on UI that shows employee data so here this table is created using view object.

3. Controller

It is that part of MVC which makes use of both view and model.

A general event binding is written inside controller. When application starts, controller initiates the application where general events are binded. For example, on click of a button, employee object should be created. This event binding can be written inside controller.
Note: In some cases, instead of writing such a code inside controller, you can create a separate view and write the same code inside that view. Therefore, 'C' in MVC is always a point of discussion.

4. Collection

Sometimes, you want multiple models stored in a single entity. In such a case, collection is very useful. I will explain how to create collection in the example below.

Why MVC?

By making an application using MVC approach, you achieve many advantages, but I personally feel scalability and resuablity are the best benefits. When your application grows larger, you just can't go and start making changes in each and every file. Instead of that, you need to add new changes in same file and MVC structure will make sure that your code runs fine.

If you are creating an employee directory so you need to show details about every employee which will certainly be different based on individual employee. In such a case, by using MVC, you can give a general structure to employee object (called Model) and a general structure to view for every employee. After that, you can create any number of employees (each having a different detail) and each employee's details can be displayed on UI using view.
Moreover, if some other application requires the same employee object, please feel free to reuse it there. :)

Dummy App to Explain MVC in JavaScript

App Name: Task Checker

Major features:

  1. Add different tasks
  2. Delete completed tasks

HTML Structure

The HTML structure is very simple with two very important tags. First with id 'template' and another one with id 'task-box'. The template div is a generate view that will be used for displaying all the tasks. The container div is 'task-box' div. Inside this div, all the views will be appended.

JS Structure

In JS file, we have created 1 model class, 1 collection class, 1 view class and 1 controller class. We have used 'this' at multiple places, but I can't describe it for now, so please try to ignore it. I'm sure you can easily understand this example without a very good understanding of 'this'.

JavaScript
var collection = new taskCollection();

var view = new taskView();
var controller = new taskController(collection,view);
controller.init();
  1. Since model means data, our taskModel will have two variables (data is stored in variable only). Variable 'task' represents task name and 'removeFlag' helps to identify whether this particular task should be deleted or not.

    JavaScript
    function taskModel(){
    
    var task="";
    var removeFlag=false;
    
        this.setTask = function(taskName){
        task = taskName;
        }
    
        this.getTask = function(){
        return task;
        }
    
        this.setFlag = function(flag){
        removeFlag = flag;
        }
    
        this.getFlag = function(){
        return removeFlag;
        }
    }

    In this model, besides having two properties called 'task' and 'removeFlag', we have created their getters and setters also.

  2. There is one collection also called taskCollection. This function gives collection of tasks. Besides getter/setter, there are two other methods called addTask and keepTask. addTask method adds more tasks in the collection. keepTask sets the value of flag that helps in identifying whether this task should be kept or deleted.

    JavaScript
    function taskCollection(){
    
    var tasks = [];
    
        this.getTasks = function(){
        return tasks;
        }
    
        this.setTasks = function(tempTasks){
        tasks = tempTasks;
        }
    
        this.addTask = function(task){
        tasks.push(task);
        }
    
        this.keepTask = function(taskVal,flag){
        for(index in tasks){
                if(taskVal==tasks[index].getTask()){
                tasks[index].setFlag(flag);
                break;
                }
            }
        }
    }
  3. After that, there is another class called taskView. This is a view for our app. Here, two methods are created, viz, showAllTasks and showTask. Here, the method showAllTasks is very important. This method gets all the tasks from task collection created in the previous step. After receiving all the tasks, it displays all those tasks where flag is set to false and it finally updates task collection with all these tasks which are still active (Remember, Task collection is a collection of models and each model has a property 'flag').

    There is another method called showTask, this method just displays individual task, i.e., whichever model is passed to this method. But in case of showAlltasks, all the tasks are displayed from collection and having property flag set to false.

    Please note that showAllTasks is called when any task is deleted and all other tasks are redisplayed whereas showTask is called whenever any task is added.

    JavaScript
    function taskView(){
    
        var template = $('.task','#template');
        this.showAllTasks=function(taskAllCollection){
    
        var tempCollectionTasks=[];
        var taskCollection = taskAllCollection.getTasks();
        var len = taskCollection.length;
    
        $('#task-box').html("");
    
        for(index=0;index<len;index++){
                var task = taskCollection[index];
                var template = $("#template");
                if(!task.getFlag()){
                template.find('.task').html(task.getTask());
                $('#task-box').append(template.html());
                tempCollectionTasks.push(task);
                }
        }
            taskAllCollection.setTasks(tempCollectionTasks);
        }
    
        this.showTask = function(taskModel){
                var template = $("#template");
                template.find('.task').html(taskModel.getTask());
                $('#task-box').append(template.html());
        }
    }
  4. After that, there is one more class which is our controller. Controller uses both view and collection objects. Here, the method init is created that binds event on add button. This method creates an object of model, sets task on this model, adds this model to collection and shows this model details using its view.

    I think, once you see the code, the remaining code is self-explanatory.

    JavaScript
    function taskController(collection,view){
    
        this.init= function(){
            $('#add-btn').off('click').on('click',function(){
            var taskVal = $('#task-name').val();
            if(taskVal.trim()!=''){
                $('#task-name').val('');
                var model = new taskModel();
                    model.setTask(taskVal);
                    collection.addTask(model);
                    view.showTask(model);
            }
            else{
                alert('Please enter some value!!');
                return;
            }
    
            });
            this.addEvent();
        }
    
        this.addEvent = function(){
          $('#task-box').off('click').on('click','.close',function(ev){
            if($(ev.currentTarget).is(':checked')) {
                $(ev.currentTarget).parent().css('text-decoration','line-through');
                var taskVal = $(ev.currentTarget).parent().find('.task').text();
                collection.keepTask(taskVal,true);
    
            }
            else{
                $(ev.currentTarget).parent().css('text-decoration','none');
                var taskVal = $(ev.currentTarget).parent().find('.task').text();
                collection.keepTask(taskVal,false)
            }
        });
    
        $('#remove-btn').off('click').on('click',function(){
            view.showAllTasks(collection);
        });
    
        }
    }
  5. Finally, you need to create these objects to make the application run fine.

History

  • 2nd December, 2014: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)