backbone.jsbackbone-relational

creating nested structure with backbone-relational


I'm trying to create a three cascading dropdown lists. First one constains projects, second contains tasks for selected project and the last one sites for selected task.

I want to use the Backbone-Relational plugin, but have hard time to create the proper relations. That's my first time with this plugin.

Code so far:

App.Models.ProjectItem = Backbone.RelationalModel.extend({
    default: {
        id: 0,
        name: ''
    },
    relations: [{
        type: Backbone.HasMany,
        key: 'tasks',
        relatedModel: App.Models.TaskItem,
        //includeInJSON: Backbone.Model.prototype.idAttribute,
        collectionType: App.Collections.TasksCollection,
        reverseRelation: {
            key: 'projectId',
            //includeInJSON: Backbone.Model.prototype.idAttribute,
            type: Backbone.HasOne
        }
    }]
});

App.Collections.ProjectsCollection = Backbone.Collection.extend({
    model: App.Models.ProjectItem
});

App.Models.TaskItem = Backbone.RelationalModel.extend({
    default: {
        id: 0,
        name: ''
    },
    relations: [{
        type: Backbone.HasMany,
        key: 'sites',
        relatedModel: App.Models.SiteItem,
        includeInJSON: Backbone.Model.prototype.idAttribute,
        collectionType: App.Collections.SitesCollection,
        reverseRelation: {
            key: 'taskId',
            //includeInJSON: Backbone.Model.prototype.idAttribute,
            type: Backbone.HasOne
        }
    }]
});

App.Collections.TasksCollection = Backbone.Collection.extend({
    model: App.Models.TaskItem
});

App.Models.SiteItem = Backbone.RelationalModel.extend({
    default: {
        id: 0,
        name: ''
    }
});

App.Collections.SitesCollection = Backbone.Collection.extend({
    model: App.Models.SiteItem
});

Creating single project:

var item = new App.Models.ProjectItem({
  id: 1,
  name: 'project',
  tasks: [
    {
      id: 1,
      name: 'task',
      sites: [
        {
          id: 1,
          name: 'site'
        }
      ]
    }
  ]
})

This object serialized to json looks like this:

"{"id":1,"name":"task","tasks":[1],"sites":[{"id":1,"name":"site"}],"projectId":null}"

My questions:

1) Why the sites array is not nested in the tasks one?

2) Sites collection is not serialized the same way that tasks one is. Should I create a relations in the site model too?

3) Why the projectId is returned for the root?


Solution

  • After many hours of trials and errors I finally got it. The order matters.. Working code:

    App.Models.SiteItem = Backbone.RelationalModel.extend({
        default: {
            siteId: 0,
            name: ''
        }
    });
    
    App.Collections.SitesCollection = Backbone.Collection.extend({
        model: App.Models.SiteItem
    });
    
    App.Models.TaskItem = Backbone.RelationalModel.extend({
        default: {
            taskId: 0,
            name: ''
        },
        relations: [{
            type: Backbone.HasMany,
            key: 'sites',
            relatedModel: App.Models.SiteItem,
            //includeInJSON: Backbone.Model.prototype.idAttribute,
            collectionType: App.Collections.SitesCollection,
            reverseRelation: {
                key: 'task',
                includeInJSON: 'taskId',
                type: Backbone.HasOne
            }
        }]
    });
    
    App.Collections.TasksCollection = Backbone.Collection.extend({
        model: App.Models.TaskItem
    });
    
    App.Models.ProjectItem = Backbone.RelationalModel.extend({
        default: {
            projectId: 0,
            name: ''
        },
        relations: [{
            type: Backbone.HasMany,
            key: 'tasks',
            relatedModel: App.Models.TaskItem,
            //  includeInJSON: 'taskId',
            collectionType: App.Collections.TasksCollection,
            reverseRelation: {
                key: 'project',
                includeInJSON: 'projectId',
                type: Backbone.HasOne
            }
        }]
    });
    
    App.Collections.ProjectsCollection = Backbone.Collection.extend({
        model: App.Models.ProjectItem
    });
    

    For sample data:

    var item = new App.Models.ProjectItem({
      projectId: 2,
      name: 'first',
      tasks: [
        {
          taskId: 1,
          name: 'task',
          sites:[{siteId:1, name: 'site'}]
        }
      ]
    });
    

    I got this json string:

    "{"projectId":2,"name":"first","tasks":[{"taskId":1,"name":"task","sites":[{"siteId":1,"name":"site","task":1}],"project":2}]}"