Reputation: 7990
When a user goes to http://example.com/#/playlist
, I want to list some songs.
It works (all songs are listed) when you first go to http://example.com
and click on the link <a href="#/playlist">Playlist</a>
.
But if you directly go to http://example.com/#/playlist
, nothing is shown.
When I log the this.collection property, the collection is always the same (if you use the link, or directly access).
The only difference is that this.collection.each( function ( song ) {} );
in the render-function below, doesn't loop when directly accessing the URL.
This is the code:
define(
[
'jQuery',
'Underscore',
'Backbone',
'collections/songlist',
'views/song'
],
function ($, _, Backbone, SonglistCollection, SongView)
{
var PlaylistView = Backbone.View.extend({
// properties
el: '#content',
tagName: 'ul',
collection: new SonglistCollection(),
/**
* Initialize
*/
initialize: function()
{
// load songs
this.collection.bind( 'reset', this.render(), this );
this.collection.fetch();
},
/**
* Render
*/
render: function ()
{
this.$el.html('');
console.log(this.collection);
this.collection.each( function ( song )
{
var songItem = new SongView( { model: song } );
this.$el.append( songItem.el );
}, this);
}
});
return new PlaylistView;
}
);
The problem occurs here, in the 'each-loop':
render: function ()
{
this.$el.html('');
console.log(this.collection);
this.collection.each( function ( song )
{
var songItem = new SongView( { model: song } );
this.$el.append( songItem.el );
}, this);
}
UPDATE
This is my routing code:
define([
'jQuery',
'Underscore',
'Backbone',
'views/start',
'views/playlist'
],
function ($, _, Backbone, startView, playlistView)
{
var AppRouter = Backbone.Router.extend({
routes: {
'playlist': 'playlist',
// default
'*actions': 'start'
},
start: function ()
{
// call render on the module we loaded via the dependency array
// views/items/list
startView.render();
},
playlist: function ()
{
playlistView.render();
},
defaultAction: function ( actions )
{
// no default action, let's just log what the url was
console.log('No route:', actions)
}
});
var initialize = function ()
{
var app_router = new AppRouter;
Backbone.history.start();
}
return {
initialize: initialize
};
}
);
Upvotes: 2
Views: 306
Reputation: 1145
In the MVC pattern, the view responds to changes in the model. You have that set up in your code with:
this.collection.on('reset', this.render, this);
But the problem is that you're not causing a reset that would in turn cause your view to re-render. So instead of invoking the render method in 'playlist,' change the url of the collection to the appropriate REST endpoint, then do a collection.fetch. Once you do the fetch, a 'reset' will be fired, and your render will then be invoked, properly reflecting the updated collection.
Upvotes: 0
Reputation: 18566
I assume that the problem is related to the fact that you initialize your PlayListView
before returning it to require.js
. Also you arbitrarily call the PlaylistView's render
method before the collection is definitely done with fetching.
http://example.com
:
http://example.com/#/playlist
:
Change this line
return new PlaylistView;
to this
return PlaylistView;
and the Router
of course should be changed as well
function ($, _, Backbone, startView, **PlaylistView**) // change the variable name
...
var AppRouter = Backbone.Router.extend({
...
playlistView: null, // Add attribute for the router
...
playlist: function () {
playlistView = new PlayListView();
// No render because you bound the render to the reset of the collection !!!
},
...
}
...
Now you won't be initializing your PlaylistView while something necessary is still left unloaded.
Upvotes: 0
Reputation: 38792
I think the problem is that when you call playlistView.render();
in the Router
the playlist.collection
is still not populated.
You are trusting in what the console.log(this.collection);
is showing to you but you can't trust in console.log()
with complex objects.
Check:
Upvotes: 1