Learning About Multiple Views in Backbone.JS

Introduction

In this article we will learn about multiple views. We will understand how a view manages the updates or the events in another view. In this tutorial we will create a record list and when we click on any record from the list then that record will be displayed in the textboxes, we can edit this record and again save it in the list.

Here we will crate a list of animal records. When a user wants to select a record then the user clicks on the record then the record will be displayed automatically in the textboxes. And the user can easily update records.

The major concept to understand about this is that the child animal view is not familiar with the detailed view. Not any of the views are familiar with the other. This is important to understand about because  it decouples the views. This is allows deletion of the view without updating the other views.

Now let's see how to create this application.

  1. First we need to create the web application as in the following:
  • Start Visual Studio 2013.
  • From the Start window select "New Project".
  • Select "Installed" -> "Template" -> "Visual C#" -> "Web" -> "Visual Studio 2012" and select "ASP.NET Empty Web Application".

Create Web Application

  • Click on the "OK" button.
  1. Now add the HTML Page to the project:
  • In the Solution Explorer.
  • Right-click on the project and select "Add" -> "HTML Page".

Add HTML Page

  • Change the name.

Change Name

  • Then click on the "OK" button.

Add the following code:

<html>

<head>

    <title></title>

    <script src="js/jquery-1.8.3.js" type="text/javascript"></script>

    <script src="js/underscore.js" type="text/javascript"></script>

    <script src="js/backbone.js" type="text/javascript"></script>

    <style>

        div .table {

            displaytable;

            border#ff0000 solid 1px;

            padding5px;

        }

 

        div .tableRow {

            displaytable-row;

        }

        div .tableCell {

            displaytable-cell;

            border#737373 solid 1px;

            padding5px;

        }

    </style>

</head>

<body>

    <div id="main" class="table"></div>

    <script type="text/template" id="template-animalItem">

        <div id="name" class="tableCell"><%=name%></div>

        <div id="color" class="tableCell"><%=color%></div>

    </script>

    <div id="mainedit">

        Name <input type="text" id="animalname" />

        Animal Color <input type="text" id="animalcolor" />

        <input type="button" id="butChange" value="Update Data" />

    </div>

    <script type="text/javascript">

        var PubSub = function () {

            this.events = _.extend({}, Backbone.Events);

        };

        var pubSub = new PubSub();

        //Create AnimalListView and loop through animals

        var Animal = Backbone.Model.extend({});

        var Animals = Backbone.Collection.extend({

            model: Animal

        });

        var AnimalListView = Backbone.View.extend({

            type: "AnimalListView"//for debugging

            el: "#main",  //the view should be decoupled from the DOM, but for this example this will do.

            //collection:  This will be passed at the time of initialization

            initialize: function () {

            },

            render: function () {

                _.each(this.collection.models, this.processAnimal, this);

                return this;

            },

            processAnimal: function (animal) {

                var childAnimalItemView = new AnimalItemView({ model: animal });

                childAnimalItemView.render();

                this.$el.append(childAnimalItemView.el);

            }

        });

        var AnimalItemView = Backbone.View.extend({

            type: "AnimalItemView"//for debugging

            template: _.template($("#template-animalItem").html()),

            tagName: "div",

            className: "tableRow",

            initialize: function () {

                this.model.on("change"this.modelChanged, this);

            },

            events: {

                "click""viewClicked"

            },

            render: function () {

                var outputHtml = this.template(this.model.toJSON());

                this.$el.html(outputHtml);

                return this;

            },

            modelChanged: function (model, changes) {

                console.log("modelChanged:" + model.get("name"));

                this.render();

            },

            viewClicked: function (event) {

                console.log("viewClicked: " + this.model.get("name"));

                pubSub.events.trigger("animal:selected"this.model);

            }

        });

        var AnimalDetailView = Backbone.View.extend({

            el: "#mainedit",

            initialize: function () {

                pubSub.events.on("animal:selected"this.animalSelected, this);

            },

            events: {

                "click  #butChange""viewChanged"

            },

            render: function () {

                var name = this.model.get("name");

                this.$el.find("#animalname").val(name);

 

                var color = this.model.get("color");

                this.$el.find("#animalcolor").val(color);

            },

            animalSelected: function (animal) {

                console.log(animal);

                this.model = animal;

                this.render();

            },

            viewChanged: function () {

                var name = this.$el.find("#animalname").val();

                this.model.set({ "name": name });

 

                var color = this.$el.find("#animalcolor").val();

                this.model.set({ "color": color });

            }

        });

        var myAnimals = [

            { "id""1""name""Lion""color""Brown" },

            { "id""2""name""Tiger""color""Brown" },

            { "id""3""name""Elephant""color""Black" },

            { "id""4""name""Dog""color""White"},

            { "id""5""name""Rabbit""color""white" }

        ];

        var animals = new Animals(myAnimals);

        var animalListView = new AnimalListView({ collection: animals });

        animalListView.render();

        var animalDetailView = new AnimalDetailView();

    </script>

</body>

</html>

In the code above we used this HTML code:

<div id="mainedit">

        Name <input type="text" id="animalname" />

        Animal Color <input type="text" id="animalcolor" />

        <input type="button" id="butChange" value="Update Data" />

    </div>

This HTML code is monitored by the View. Here the user can update the name and color of the animals. There is nothing special, there is only a display of two textboxes and a single button. These input controls are put inside the <div> that has the id "main". It allows the user to use the backbone.js view  to monitor the elements and its children.

 var PubSub = function () {

            this.events = _.extend({}, Backbone.Events);

        };

        var pubSub = new PubSub();

There is a variable "PubSub", referenced many times in the various views. This describes how the various views communicate with each other.

 viewClicked: function (event) {

                console.log("viewClicked: " + this.model.get("name"));

                pubSub.events.trigger("animal:selected"this.model);

            }

When the "viewClicked" is invoked, then we use the objects of the "pubsub.events" to trigger an event that invokes "animal:selected". Here we will also pass the model that is monitored by the view. And at the same time "pubsub" notifies the others granted to the "animal:selected" event and transfers them to the animal. Now let us see the results:

Displaylist

When we click on the record in the table it will be displayed in the textboxes.

SelectRecord

Now we can modify it.

Update Record