简体   繁体   中英

Backbone.js and nested collections

This is a detailed question (with some of mmy code) of this other one: Backbone nested views

The other question contains a graphical representation of what I'm trying to achieve, but I think that if I write some code that'll help my question get resolved.

I have a big array or data of the following structure:

[
    {
        window: { <window-relative data>},
        tabs: [
            { <tab-relative data>},
            { <tab-relative data>}
        ]
    },

    {
        window: { <window-relative data>},
        tabs: [
            { <tab-relative data>},
            { <tab-relative data>}
        ]
    }
]

I can't query just the tabs of a window, nor just a single window. The data is as-is and there is no possibility at splitting it in any way. Let's just leave it at that the data is bootstrapped (and the way that it's bootstrapped can't be changed).

Keeping on with the question: I have a WindowsCollection:

myapp.WindowCollection = Backbone.Collection.extend({
    model : WindowModel,

    initialize: function(){
        this.bind('reset', this.onReset);
    },

    onReset: function(){
        // ...
    }

});

And a tabs collection which looks pretty much the same. I also have a Window model and a Tab model.

When the page loads completely, the following code is ran to load the data into the window collection: myapp.myWindowCollection.reset(<data here>);

My question is: where and how should I initialize the tab collections? In the ```onReset``? Let's assume I do something like

onReset: function(){
    _.each(this.models, function(window_data){
        t = new TabsCollection();
        t.reset(window_data.tabs);
    });
}

Then my nested collections (the Tabs collections) will have the right data, but then how could I create the view of each Tabs collection?

I could do:

onReset: function(){
    _.each(this.models, function(window_data){
        t = new TabsCollection();
        t.reset(window_data.tabs);
        tv = new TabsCollectionView(
            collection: t;
        );
    });
}

but then I would be messing views and collections and I'm feeling this is really messy. Is there some better way that doesn't involve messing with views and collections in the same place?

I'm just posting this here so others can see how I solved the problem

A working demo of the solution can be found here: http://jsfiddle.net/NH9J6/146/

As you can see from the link, the work is done thanks to Marionette's CompositeView which lets recursively render collections.

var TreeView = Backbone.Marionette.CompositeView.extend({

    initialize: function(){
        if(this.model.tabs){
            this.template = "#window-template";
        }else{
            this.template = "#tab-template";
        }
        this.collection = this.model.tabs;
    },

    appendHtml: function(cv, iv){
        cv.$("#tabs").append(iv.el);
    },
    onRender: function() {
        if(_.isUndefined(this.collection)){
            this.$("#tabs").remove();
        }
    }
});

The small trick I'm using in the initialize (the if/else with the template asignation) works the following way:

I get the current model and check if it has a "tabs" key. If it does have it, it means that the current model is a Window Data Model, so I need to use the window-template , else use the tab-template

The rest is pretty much plain Backbone structure.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM