Collection is empty when a route calls it, but if I go away and come back, the collection holds what it is supposed to

StackOverflow https://stackoverflow.com/questions/19527418

質問

The code works every-time EXCEPT for when the router is first called with page load. The, the collection is created, but it's not populated with the notes.fetch();. I've been looking all over, and I can't see why this is happening.

For example, when I go to the URL to load this page, everything but what is in the collection loads. When I go to #blank/' and then go "Back" to thelist` view, the collection AND the models load as they are supposed to. SO how do I get the collection to load once the page loads?

Here's the code:

$(function() {

    // Note: The model and collection are extended from TastypieModel and TastypieCollection
    // to handle the parsing and URLs

    window.Note = TastypieModel.extend({});

    window.Notes = TastypieCollection.extend({
        model: Note,
        url: NOTES_API_URL
    });

    window.notes = new Notes();

    window.NoteView = Backbone.View.extend({

        className: "panel panel-default note",
        template: _.template($('#notes-item').html()),
        events: {
            'click .note .edit': 'editNoteToggle',
            'click .note .edit-note': 'doEdit'
        },
        initialize: function () {
            _.bindAll(this, 'render');
            this.model.bind('change', this.render);
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        },
        editNoteToggle: function() {
            console.log("I've toggled the edit box");
        },
        doEdit: function() {
            console.log('This will edit the note');
        }
    });

    window.NoteListView = Backbone.View.extend({

        el: "#app",
        template: _.template($('#notes-item-list').html()),
        events: {
            'click #add-note': 'addNote'
        },
        initialize: function () {
            _.bindAll(this, 'render', 'addNote');
            this.collection.bind('change', this.render);
        },
        render: function() {
            this.$el.html(this.template());
            console.log('before the loop');
            console.log(this.collection.toJSON()); //<- Empty when it first loads, then contains the models when I visit another page and come "back" to this page
            this.collection.each(function(note){
                var view = new NoteView({ model: note });
                $('#notes-list').append(view.render().el);
            });
            console.log('done');
            $('#add-note-toggle').on('click', this, function() {
                $('#note-add-form').toggle();
            });
            return this;
        },
        addNote: function() {
            console.log('The add note was clicked');
        }
    });

    window.NotesRouter = Backbone.Router.extend({
        routes: {
            '': 'list',
            'blank/': 'blank'
        },
        initialize: function() {
            // starts by assigning the collection to a variable so that it can load the collection
            this.notesView = new NoteListView({
                collection: notes
            });
            notes.fetch();
        },
        list: function () {
            $('#app').empty();
            $('#app').append(this.notesView.render().el);
        },
        blank: function() {
            $('#app').empty();
            $('#app').text('Another view');
        }
    });

    window.notesRouter = new NotesRouter();
    Backbone.history.start();
})
役に立ちましたか?

解決

It looks like your listening to the wrong collection event. Try using

window.NoteListView = Backbone.View.extend({
    // ...
    initialize: function () {
        this.collection.bind('reset', this.render);
    }
    // ...
});
window.NotesRouter = Backbone.Router.extend({
    // ...
    initialize: function() {
        notes.fetch({reset: true});
    }
    // ...
});

Right now you are firing off an async collection.fetch(), which will eventually load the data. Problem is, once that data is loaded into the collection, it won't fire a change event, just a bunch of adds. When you go to the blank page and back, you're data has arrived by the second render call and displays properly.

If you modify your fetch() to throw a reset event and then listen for that, you'll have a freshly rendered NoteList once the data comes in without the need to go to the blank page.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top