Dynamically changing url in Backbone
backbone.js, javascript, json
Solution
There are numerous different ways of doing this. Here's what's probably going to be 'best practice'.
App.Controllers.Documents = Backbone.Router.extend({
routes:{
"recent" : "recent",
"popular" : "popular",
"featured" : "featured",
},
initialize: function () {
this.collection = new App.Collections.Posts();
},
_showPage: function (config) {
$("#browser").empty();
this.collection.fetch({
url: config.url,
success: function(col,posts){
new App.Views.GuideView({collection: posts});
},
error: function(error){
console.log(error)
}
});
},
recent: function(){
this._showPage({url:'http://localhost:5000/json/posts/recent'});
},
popular: function(){
this._showPage({url:'http://localhost:5000/json/posts/popular'});
},
featured: function(){
this._showPage({url:'http://localhost:5000/json/posts/featured'});
}
});
Since I really don't know how complicated your page is going to get, this is probably the best I can do without more information. But, the idea is that "this.collection" is set on the routers initialization.. so you can keep reusing it. The _showPage method does whatever basic tasks you need done to show the page, and the methods called by the routes use it to do whatever basic stuff needs done before going into detail. The url passed into the config would simply tell the collection where to get its information from - I'm assuming that all of your data has the same format and 'is the same thing'.. just different filters.
You can probably do a similar thing with `App.Views.GuideView`:
App.Controllers.Documents = Backbone.Router.extend({
routes:{
"recent" : "recent",
"popular" : "popular",
"featured" : "featured",
},
initialize: function () {
this.collection = new App.Collections.Posts();
this.view = new App.Views.GuideView({collection: this.collection});
},
_showPage: function (config) {
$("#browser").empty();
this.collection.fetch({
url: config.url,
success: _.bind(function(col,posts){
this.view.render();
}, this),
error: function(error){
console.log(error)
}
});
},
recent: function(){
this._showPage({url:'http://localhost:5000/json/posts/recent'});
},
popular: function(){
this._showPage({url:'http://localhost:5000/json/posts/popular'});
},
featured: function(){
this._showPage({url:'http://localhost:5000/json/posts/featured'});
}
});
The 'render' would just rebuild the view, and since you've already got the collection referenced in the view as "this.options.collection" (or you could add an 'initialize' to the view and set this.collection to be this.options.collection). When the collection gets updated, all of that information is by reference in the view.. so no need to reset it.
Problem
I was trying to dynamically change the url inside the router but couldn't manage to do it, it keeps returning to the base Collection URL. Here i posted the code with the 3 different collections which apart from pointing to three different urls they do exactly the same. I have only one `model` and three `collections` that depend on that model and they even render the same view. How can i dynamically change the `url` so i can create only one `Collection` and one `Model`? Is it best pracitce for a case like this? ``` // MODELS & COLLECTIONS window.Post = Backbone.Model.extend({ urlRoot: function() { return 'http://localhost:5000/json/guides/:id' } }) App.Collections.RecentPosts = Backbone.Collection.extend({ model: Post, url:'http://localhost:5000/json/posts/recent', }) App.Collections.PopularPosts = Backbone.Collection.extend({ model: Post, url:'http://localhost:5000/json/posts/popular', }) App.Collections.FeaturedPosts = Backbone.Collection.extend({ model: Post, url:'http://localhost:5000/json/posts/featured', }) // CONTROLLER App.Controllers.Documents = Backbone.Router.extend({ routes:{ "recent" : "recent", "popular" : "popular", "featured" : "featured", }, recent: function(){ //.... same as featured ? }, popular: function(){ //.... same as featured ? }, featured: function(){ $("#browser").empty(); var collection = new App.Collections.Posts(); collection.fetch({ success: function(col,posts){ new App.Views.GuideView({collection: posts}); }, error: function(error){ console.log(error) } }) } }); ```