0
votes

I have a backbone application that looks like this:

// Model for one picture
var Picture= Backbone.Model.extend({ });

// Model for Collection of Pictures
var Pictures = Backbone.Collection.extend({ model:Picture });

// Model for album
var Album = Backbone.Model.extend();

//Model for a collection of Albums
var Albums = Backbone.Collection.extend({ model:Album });

My server supports the following functions

List<Album> GetAlbums(List<Guid> albumIds);
List<Picture> GetPictures(albumId);
Dictionary<string, string> GetAlbumMetadata(albumId);
Dictionary<string, string> GetPictureMetadata(pictureId);

My page starts with one or more albums being loaded initially.

It should first get a list of albums.

Then it loads the metadata of all the albums.

Then it loads the pictures in each album.

Then it loads the metadata of each picture.

I cannot load all of it from a single server side call, because it is expensive, so I have to load it dynamically.

Is there a simple, backbone specific way of loading all this dynamically? Currently, I am reading the JSON returned on fetch() of each function, and then making the next function call based on the results returned from each call.

There has to be a more elegant way of doing this.

1
initially you have albums ids, right? and where do pictures ids come from?Michael Radionov
Yes. Album object has a List<Guid> which is the id of all the pictures in that album.ashwnacharya

1 Answers

1
votes

Here is my possible solution, I was relying on initialize methods. It's better to read a code from the bottom, order is reversed due to definitions. Sorry, had not tested the code.

// Model for one picture
var Picture = Backbone.Model.extend({
    // use urlRoot
    // if after "pictures" fetch picture has an 'id' property,
    // it will be appended to urlRoot on "picture" fetch
    urlRoot: '/picture/metadata',
    initialize: function() {
        // get metadata for current picture
        this.fetch();
    }
});

// Model for Collection of Pictures
var Pictures = Backbone.Collection.extend({
    model: Picture,
    initialize: function(models, options) {
        // get passed album id
        this.album_id = options.album_id;
        // automatically fetch pictures when collection is created from album model
        // When items are fetched, Picture models are automatically created
        // and their 'initialize' method is called
        this.fetch();
    },
    // url property may be a function too
    url: function() {
        return '/pictures/' + this.album_id;
    }
});

// Model for album
var Album = Backbone.Model.extend({
    // use urlRoot
    // if after "albums" fetch album has an 'id' property,
    // it will be appended to urlRoot on "album" fetch
    urlRoot: '/album/metadata',
    initialize: function() {
        // get metadata for current album
        this.fetch();

        // initialize pictures collection for current album
        // pass album id
        var pictures = new Pictures([], { album_id: this.get('id') });
        this.set('pictures', pictures);
    }
});

//Model for a collection of Albums
var Albums = Backbone.Collection.extend({
    url: '/albums'
    model: Album
});

// Create albums collection
var albums = new Albums();

// Get specific albums by ids
// When items are fetched, Album models are automatically created
// and their 'initialize' method is called
albums.fetch({
    data : {
        ids: [1,2,3,4,5]
    }
});