backbone.associate demo

https://github.com/rjz/backbone-associate

by rjzaworski

HTML

<script src="https://rjz.github.io/backbone.associate/src/backbone.associate.js"></script>

JavaScript

// Backbone.associate -- extending associate
// see: https://github.com/rjz/backbone.associate/

var Country = Backbone.Model.extend({
    idAttribute: 'name',
    set: function (attributes) {
        var self = this,
            result = {};

        _.each(attributes, function (value, key) {
            var attribute = self.attributes[key];
            if (attribute instanceof Backbone.Collection) {
                attribute.reset(value);
            } else if (attribute instanceof Backbone.Model) {
                attribute.set(value);
            } else {
                result[key] = value;
            }
        });
        Backbone.Model.prototype.set.call(this, result);
    },
    url: function () {
        return '/countries/' + this.id;
    }
});

var Flag = Backbone.Model.extend({});
var City = Backbone.Model.extend({
    idAttribute: 'name'
});
var Cities = Backbone.Collection.extend({
    model: City
});

Backbone.associate(Country, {
    flag: {
        type: Flag
    },
    cities: {
        type: Cities
    }
});

var data = {
    name: 'Canada',
    cities: [{
        name: 'Calgary'
    }, {
        name: 'Regina'
    }]
};

var canada = new Country(data, {
    parse: true
});

// Set associate URLs as needed
canada.cities().url = canada.url() + '/cities';
canada.flag().url = canada.url() + '/flag';

console.log(canada.cities().first().url());
console.log(canada.flag().url);

// set associations directly
canada.set('cities', [{
    name: 'Saskatoon'
}, {
    name: 'Windsor'
}]);

console.log(canada.cities());

// handle child events
canada.onCityAdded = function (model) {
    console.log('city added!', model.get('name'));
}

canada.listenTo(canada.cities(), 'add', canada.onCityAdded);
canada.cities().add({
    name: 'St. John\'s'
});