Create Contact List of People With Add, Edit, Delete Event

Introduction

In this article we will create a Contact List with edit, delete and add event features in backbone.js. Here will create the four events "button.edit" , "button.Save", "button.cancle" in the contact View.

"click button.delete""deletePerson",

            "click button.edit""editPerson",

            "change select.type""addType",

            "click button.save""saveEdits",

            "click button.cancel""cancelEdit"

Use the following procedure to create the application.

Step 1

  • Start Visual Studio 2013.
  • From the Start window select "New project".
  • Select "Installed" -> "Template" -> "Visual C#" -> "Web" -> "Visual Studio 2012"and select "ASP.NET Web Application".

Add Web Application

  • Click on the "OK" button.

Step 2

Now add an 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 of the page.

Change Name

  • Click on the "OK" button.

Add the following code:

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8" />

    <title>Backbone.js Web App</title>

    <link href="style.css" rel="stylesheet" />

</head>

<body>

    <div id="persons">

        <header>

            <div id="filter"><label>Show me:</label></div>

            <a id="showForm" href="#">Add new Person</a>

            <form id="addPerson" action="#">

                <label for="name">Name:</label><input id="name" /><br />

                <label for="type">Type:</label><input id="type" /><br />

                <label for="address">Address:</label><input id="address" /><br />

                <label for="contact">Contact:</label><input id="contact" /><br />

                <label for="email">Email_Id:</label><input id="email" /><br />

                <button id="add">Add</button>

            </form>

        </header>

    </div>

    <script id="personTemplate" type="text/template">

        <img src="<%= photo %>" />

        <h1><%= name %><span><%= type %></span></h1>

        <div><%= address %></div>

        <dl>

            <dt>Contact:</dt>

            <dd><%= contact %></dd>

            <dt>Email:</dt>

            <dd><a href="mailto:<%= email %>"><%= email %></a></dd>

        </dl>

        <button class="delete">Delete</button>

        <button class="edit">Edit</button>

    </script>

   

Now adding the button for existing template, We can also add an new template that can be used as an editable form.

 <script id="personEditTemplate" type="text/template">

        <form action="#">

            <input class="name" value="<%= name %>" />

            <input id="type" type="hidden" value="<%= type %>" />

            <input class="address" value="<%= address %>" />

            <input class="contact" value="<%= contact %>" />

            <input class="email" value="<%= email %>" />

            <button class="save">Save</button>

            <button class="cancel">Cancel</button>

        </form>

    </script>

   

Now we need to add these scripts file.

 <script src="js/jquery-1.7.1.min.js"></script>

    <script src="js/json2.js"></script>

    <script src="js/underscore-min.js"></script>

    <script src="js/backbone-min.js"></script>

    <script src="js/main.js"></script>

</body>

</html>

Step 3

Now we add a JavaScript file as in the following:

  • In the Solution Explorer.
  • Right-click on the project then select "Add" -> "New Item" -> "JavaScript".

Add JavaScript file

  • Click on the "Add" button.

Add the following code:

(function ($) {

    //demo data

    var persons = [

       { name: "Person 1", address: "Address 1", contact: "0123456789", email: "[email protected]", type: "family" },

 

        { name: "Person 2", address: "Address 2", contact: "4536782947", email: "[email protected]", type: "family" },

        { name: "Person 3", address: "Address 3", contact: "5647839244", email: "[email protected]", type: "Friend" },

        { name: "Person 4", address: "Address 4", contact: "43890128743", email: "[email protected]", type: "Relative" },

         { name: "Person 5", address: "Address 5", contact: "3456789012", email: "[email protected]", type: "Relative" },

    ];

    //define model

    var Person = Backbone.Model.extend({

        defaults: {

            photo: '/img/winter.jpg',

            name: "",

            address: "",

            contact: "",

            email: "",

            type: ""

        }

    });

    //define directory collection

    var Directory = Backbone.Collection.extend({

        model: Person

    });

    //define person view

    var PersonView = Backbone.View.extend({

        tagName: "article",

        className: "person-container",

        template: _.template($("#personTemplate").html()),

        editTemplate: _.template($("#personEditTemplate").html()),

 

        render: function () {

            this.$el.html(this.template(this.model.toJSON()));

            return this;

        },

        events: {

            "click button.delete""deletePerson",

            "click button.edit""editPerson",

            "change select.type""addType",

            "click button.save""saveEdits",

            "click button.cancel""cancelEdit"

        },

        //delete a contact

        deletePerson: function () {

            var removedType = this.model.get("type").toLowerCase();

            //remove model

            this.model.destroy();

            //remove view from page

            this.remove();

            //re-render select if no more of deleted type

            if (_.indexOf(directory.getTypes(), removedType) === -1) {

                directory.$el.find("#filter select").children("[value='" + removedType + "']").remove();

            }

        },

        //switch person edit mode

        editPerson: function () {

            this.$el.html(this.editTemplate(this.model.toJSON()));

 

            //add select to set type

            var newOpt = $("<option/>", {

                html: "<em>Add new...</em>",

                value: "addType"

            });

            this.select = directory.createSelect().addClass("type").val(this.$el.find("#type").val()).append(newOpt).insertAfter(this.$el.find(".name"));

            this.$el.find("input[type='hidden']").remove();

        },

        addType: function () {

            if (this.select.val() === "addType") {

                this.select.remove();

                $("<input />", {

                    "class""type"

                }).insertAfter(this.$el.find(".name")).focus();

            }

        },

        saveEdits: function (e) {

            e.preventDefault();

            var formData = {},

                prev = this.model.previousAttributes();

            //get form data

            $(e.target).closest("form").find(":input").not("button").each(function () {

                var el = $(this);

                formData[el.attr("class")] = el.val();

            });

            //use default photo if none supplied

            if (formData.photo === "") {

                delete formData.photo;

            }

            //update model

            this.model.set(formData);

            //render view

            this.render();

            //if model acquired default photo property, remove it

            if (prev.photo === "/img/placeholder.png") {

                delete prev.photo;

            }

            //update persons

            _.each(persons, function (person) {

                if (_.isEqual(person, prev)) {

                    persons.splice(_.indexOf(persons, person), 1, formData);

                }

            });

        },

        cancelEdit: function () {

            this.render();

        }

    });

    //define master view

    var DirectoryView = Backbone.View.extend({

        el: $("#persons"),

 

        initialize: function () {

            this.collection = new Directory(persons);

 

            this.render();

            this.$el.find("#filter").append(this.createSelect());

 

            this.on("change:filterType"this.filterByType, this);

            this.collection.on("reset"this.render, this);

            this.collection.on("add"this.renderPerson, this);

            this.collection.on("remove"this.removePerson, this);

        },

 

        render: function () {

            this.$el.find("article").remove();

 

            _.each(this.collection.models, function (item) {

                this.renderPerson(item);

            }, this);

        },

        renderPerson: function (item) {

            var personView = new PersonView({

                model: item

            });

            this.$el.append(personView.render().el);

        },

        getTypes: function () {

            return _.uniq(this.collection.pluck("type"), falsefunction (type) {

                return type.toLowerCase();

            });

        },

        createSelect: function () {

            var filter = this.$el.find("#filter"),

                select = $("<select/>", {

                    html: "<option value='all'>All</option>"

                });

 

            _.each(this.getTypes(), function (item) {

                var option = $("<option/>", {

                    value: item.toLowerCase(),

                    text: item.toLowerCase()

                }).appendTo(select);

            });

            return select;

        },

        //add ui events

        events: {

            "change #filter select""setFilter",

            "click #add""addPerson",

            "click #showForm""showForm"

        },

        //Set filter property and fire change event

        setFilter: function (e) {

            this.filterType = e.currentTarget.value;

            this.trigger("change:filterType");

        },

        //filter the view

        filterByType: function () {

            if (this.filterType === "all") {

                this.collection.reset(persons);

                personsRouter.navigate("filter/all");

            } else {

                this.collection.reset(persons, { silent: true });

 

                var filterType = this.filterType,

                    filtered = _.filter(this.collection.models, function (item) {

                        return item.get("type").toLowerCase() === filterType;

                    });

 

                this.collection.reset(filtered);

               personsRouter.navigate("filter/" + filterType);

            }

        },

        //add a new person

        addPerson: function (e) {

            e.preventDefault();

 

            var formData = {};

            $("#addPerson").children("input").each(function (i, el) {

                if ($(el).val() !== "") {

                    formData[el.id] = $(el).val();

                }

            });

            //update data store

            persons.push(formData);

            //re-render select if new type is unknown

            if (_.indexOf(this.getTypes(), formData.type) === -1) {

                this.collection.add(new Person(formData));

                this.$el.find("#filter").find("select").remove().end().append(this.createSelect());

            } else {

                this.collection.add(new Person(formData));

            }

        },

        removePerson: function (removedModel) {

            var removed = removedModel.attributes;

            //if model acquired default photo property, remove it

            if (removed.photo === "/img/placeholder.png") {

                delete removed.photo;

            }

            //remove from contacts array

            _.each(persons, function (person) {

                if (_.isEqual(person, removed)) {

                    persons.splice(_.indexOf(persons, person), 1);

                }

            });

        },

        showForm: function () {

            this.$el.find("#addPerson").slideToggle();

        }

    });

    //add routing

    var PersonsRouter = Backbone.Router.extend({

        routes: {

            "filter/:type""urlFilter"

        },

        urlFilter: function (type) {

            directory.filterType = type;

            directory.trigger("change:filterType");

        }

    });

    //create instance of master view

    var directory = new DirectoryView();

    //create router instance

    var personsRouter = new PersonsRouter();

    //start history service

    Backbone.history.start();

}(jQuery));

Step 4

Now we add a Style Sheet:

  • In the Solution Explorer.
  • Right-click on the project then select "Add" -> "New Item" -> "Style Sheet".

Add StyleSheet

  • Click on the "Add" button.

Add the following code:

#persons {width:1300pxmargin:auto; }

.person-container { width:400pxpadding:10pxborder:1px solid #aaamargin:0 10px 10px 0position:relativefloat:leftfont-family:sans-serifcolor:#333background-color:#eee; }

.person-container h1 { margin:0font-weight:normal; }

.person-container h1 span { float:rightfont-size:14pxline-height:24pxfont-weight:normal; }

.person-container img { border-width:1pxborder-style:solidborder-color:#fffborder-right-color:#aaaborder-bottom-color:#aaamargin-right:10pxfloat:leftheight:50px ;width:50px;}

.person-container div { margin-bottom:24pxfont-size:14px; }

.person-container a { color:#333;}

.person-container dl { margin:0float:leftfont-size:14px; }

.person-container dt.person-container dd { margin:0float:left; }

.person-container dt { width:50pxclear:left; }

.person-container button { margin-top:10pxfloat:right; }

 

header { margin-bottom:10px; }

header:after { content:""display:blockheight:0visibility:hiddenclear:bothfont-size:0line-height:0; }

 

#filter { float:left; }

#showForm { float:right; }

#addPerson { display:nonewidth:466pxfloat:rightclear:bothfont-family:sans-seriffont-size:14px; }

#addPerson label { width:60pxmargin-right:10pxtext-align:rightline-height:25px; }

#addPerson label#addPerson input { display:blockmargin-bottom:10pxfloat:left; }

#address { width:380pxmargin-left:2px; }

#addPerson label[for="name"]#addPerson label[for="address"]#addPerson label[for="contact"] { clear:both; }

#addPerson button { display:blockmargin:10px 10px 0 0float:rightclear:both; }

 

.person-container input.person-container select { display:blockmargin:0float:left; }

.person-container .name.person-container .address { clear:left; }

.person-container input { margin:0 10px 3px 0; }

.person-container .address { width:395pxmargin-right:0; }

.person-container .contact { width:90px; }

.person-container form button { margin:5px 0 0; }

Step 5

Now execute the application.

We can see the output like this. There is a display of the record for the person with edit and save buttons and an Add new Data link is displayed.

Display record

Add new Person

 
Edit Record 

 


Similar Articles