Search code examples
javascriptjquerybackbone.jsbackbone-viewsbackbone-model

Objects not being removed from collection in Backbone


this is the jsfiddle

What am I trying to achieve?

I'm trying to create a message client using this tutorial, I'm at the part where an object gets removed from the view.

What happens when I click delete?

For some reason the remove function gets called, throws no error and does nothing. I'm convinced that it has something to do with the "removedMessage.attributes" on the removeMessage event being undefined?

the html

    <!--  BACKBONE TEMPLATE --->
    <div id="messages" style="width: 600px">  
        <form id="addMessage" action="#">
            <div>
                <label for="messageText">Message: </label>
                <input id="messageText" name="message" type="text" />
                <button id="add">Add</button>
            </div>
        </form>
    </div>

   <script type="text/template" id="messageTemplate">
       <button class="delete place-right">delete</button>

       <a class="list autoWidth <% if(has_been_read) { %> selected <% } %>">
           <div class="list-content">
               <img src="//www.polyvore.com/cgi/img-thing?.out=jpg&size=l&tid=20774792" class="icon">
               <div class="data">
                   <span class="item-title-secondary fg-gray"><b><%= sender %></b></span>
               </div>
                    <span class="tertiary-text">
                        <%= message %>
                    </span>
           </div>
       </a>
   </script>

the javascript

    var messagesjson = [
        {
            id: 3,
            message: "This is the message",
            sender: "gabriel",
            receiver: "gabriel",
            has_been_read: false,
            has_been_reported: false,
            created_at: "2014-10-23T19:55:20+0200",
            is_friend: false
        },
        {
            id: 5,
            message: "I'm loving this ",
            sender: "gabriel",
            receiver: "gabriel",
            has_been_read: true,
            has_been_reported: false,
            created_at: "2014-10-23T20:02:34+0200",
            is_friend: false
        }];

    var MessageModel = Backbone.Model.extend({
        defaults:
        {
            id: null,
            message: "This is the message",
            sender: "gabriel",
            receiver: "gabriel",
            has_been_read: false,
            has_been_reported: false,
            created_at: "2014-10-23T19:55:20+0200",
            is_friend: false
        }
    });

    var MessageView = Backbone.View.extend({
        tagName: "div",
        className: "listview",
        template: $('#messageTemplate').html(),
        render: function()
        {
            var tmpl = _.template(this.template);
            console.log(this.model);
            this.$el.html(tmpl(this.model.toJSON()));
            return this;
        }
    });

    var MessageCollection = Backbone.Collection.extend({
        model: MessageModel
    });

    var MessageCollectionView = Backbone.View.extend({
        el: $('#messages'),
        initialize: function()
        {
            this.collection = new MessageCollection(messagesjson);
            this.render();
            this.collection.on("add", this.renderMessage, this);
            this.collection.on("remove", this.removeMessage, this);
        },
        render: function()
        {
            var that = this;
            _.each(this.collection.models, function(item){
                that.renderMessage(item);
            },this);
        },
        events:{
            "click #add":"addMessage",
            "click .delete": "removeMessage"
        },
        renderMessage: function(item)
        {
            var messageview = new MessageView({
                model: item
            });

            this.$el.append(messageview.render().el);
        },
        addMessage: function(e)
        {
            e.preventDefault();
            var formData = {};

            $("#addMessage").find("input").each(function (i, el) {
                formData[el.name] = $(el).val();
            });

            messagesjson.push(formData);
            this.collection.add(new MessageModel(formData));

            console.log(messagesjson);
        },
        removeMessage: function(removedMessage)
        {
            console.log('called function');
            console.log("why is this "+removedMessage.attributes+"?");
            var removedMessageData = removedMessage.attributes;

            _.each(removedMessageData, function(val, key){
                if(removedMessageData[key] === removedMessage.defaults[key]){
                    delete removedMessageData[key];
                }
            });

            _.each(messagesjson, function(message){
                if(_.isEqual(message, removedMessageData)){
                    messagesjson.splice(_.indexOf(messagesjson, message), 1);
                }
            });
        }
    });

    var messagecollectionview = new MessageCollectionView();

Solution

  • It works now I attached the event to the collection, which means "this" pointed at the whole collection instead of the single view

    the single message view

            var MessageView = Backbone.View.extend({
                tagName: "div",
                className: "listview",
                template: $('#messageTemplate').html(),
                render: function()
                {
                    var tmpl = _.template(this.template);
                    console.log(this.model);
                    this.$el.html(tmpl(this.model.toJSON()));
                    return this;
                },
                removeMessage:function () {
                    //Delete model
                    this.model.destroy();
                    //Delete view
                    this.remove();
                },
                events:{
                    "click .delete": "removeMessage"
                }
            });
    

    the collection

        var MessageCollectionView = Backbone.View.extend({
                el: $('#messages'),
                initialize: function()
                {
                    this.collection = new MessageCollection(messagesjson);
                    this.render();
                    this.collection.on("add", this.renderMessage, this);
                    this.collection.on("remove", this.removeMessage, this);
                },
                render: function()
                {
                    var that = this;
                    _.each(this.collection.models, function(item){
                        that.renderMessage(item);
                    },this);
                },
                renderMessage: function(item)
                {
                    var messageview = new MessageView({
                        model: item
                    });
    
                    this.$el.append(messageview.render().el);
                },
                addMessage: function(e)
                {
                    e.preventDefault();
                    var formData = {};
    
                    $("#addMessage").find("input").each(function (i, el) {
                        formData[el.name] = $(el).val();
                    });
    
                    messagesjson.push(formData);
                    this.collection.add(new MessageModel(formData));
    
                    console.log(messagesjson);
                },
                events:{
                    "click #add":"addMessage"
                },
                removeMessage: function(removedMessage)
                {
                    console.log('called function');
                    console.log(removedMessage);
                    var removedMessageData = removedMessage.attributes;
    
                    _.each(removedMessageData, function(val, key){
                        if(removedMessageData[key] === removedMessage.defaults[key]){
                            delete removedMessageData[key];
                        }
                    });
    
                    _.each(messagesjson, function(message){
                        if(_.isEqual(message, removedMessageData)){
                            messagesjson.splice(_.indexOf(messagesjson, message), 1);
                        }
                    });
                }
            });