0
votes

In my backbone application, I have a model that looks a little like this,

{  
    "id" : 145,
    "name" : "Group Number 1",
    "information" : "Some kind of blurb about group number 1",
    "members" : {[
       "id" : 1,  
       "first_name" : "John",
       "last_name" : "Doe",
       "email" : "[email protected]"
    ]}
}

Now if I run this.model.get('members').add(newUser) a new user gets added to the members collection within my model - however it does not fire a change event, why is this? Buy yet if I change the name of the model, then a change event is fired?

All this is done with a view that looks like this,

Individual model view

Views.OrganisationView = Backbone.View.extend({

    tagName: 'div',
    className:'group group--panel col-sm-3',

    template : _.template( $('#tpl-single-group').html() ),

    events: {
        "click a[data-type=organisation], button[data-type=organisation]" : "edit",
        "click .js-delete-group" : "removeOrganisation",
    },

    initialize: function() {
        this.model.on("error", function(model, xhr, options){
            console.log(model, xhr, options);
            console.log(this);
        });
        this.listenTo(this.model, 'change', this.render);
        this.listenTo(this.model, 'destroy', this.removeView);
    },

    render: function() {
        this.$el.html( this.template({
            group: this.model.toJSON()
        }));

        return this;
    },

    removeView: function() {
        this.remove();
    },

    removeOrganisation: function(e) {
        this.model.destory();
        this.remove();
    },

    edit: function(e) {
        e.preventDefault();
    Routes.Application.navigate('/organisation/edit/' + this.model.get('id'), { trigger: false } );
        var editClient = new Views.OrganisastionEditView({
            model: this.model
        });
    }

});

The second confusing thing that a request event gets thrown, (makes sense seen as though I am saving the model, but an error event gets thrown as well, but there are no errors the xhr and I am not currently validating the model?

Here is how I am saving the user to members collection in my model,

var member = new Pops.Models.User({ id: element.data('id') });
member.fetch({
    success:function() {
        self.model.get('members').add(member);
        var model = self.model;
        self.$('.search').hide();
        self.$('button').show();
        var projectMember = new Pops.Views.UserInitialsWithAdmin({
            model: member
        });
        self.model.save({validate:false});
        self.$('.search').parent().append( projectMember.render().el );
        self.$('.search').remove();
    }
});
1
There is a bit of confusion with declaration of models and collections in your example. In a first example of object members attribute is another javascript object, not a Backbone.Collection, so I wonder how you calling add on it. And for your second issue - it's working as expected. request event will be thrown whenever Backbone.sync called (it is initiated by model.fetch). And if $.ajax fails it will call error callback.Vahan Vardanyan

1 Answers

0
votes

(I'm assuming the first bit of code you've given is just a guideline of what a plain JSON representation of your model would look like, and that members is a real Collection with an add method available.)

In answer to the first question: change events are only fired when changing a model attribute using set. In your case, you're adding to the collection stored in the members attribute, but the members attribute still contains a reference to the same collection it did before, which means from Backbone's perspective this attribute has not changed. I would suggest attaching listeners directly to the members collection. Also see How can I "bubble up" events on nested Backbone collections?.

In general nesting models in Backbone is not straightforward, as Jeremy Ashkenas has pointed out. It's often better to keep models flat and store references to related models as arrays of ids, which can then be fetched as necessary.