I'm trying use windows.history.back() but nothing happens. Exactly when the event call history.back appear for a few second or less only the menu of the previous page.
Below the view where the function is called:
var LandscapeView = Backbone.View.extend({
template: Handlebars.compile(template),
events: {
},
initialize: function() {
this.geolocation();
$(window).on('orientationchange', this.onOrientationChange);
},
/* render: function() {
//var context = JSON.parse(JSON.stringify(this.model));//eliminare
//var context=this.model;
var html =this.template();
this.$el.html(html);
$('#pagina').empty();
$('#pagina').append(this.$el.html(html));
return this;
},*/
geolocation:function(){
navigator.geolocation.getCurrentPosition(win);
function win(pos){
console.log("gps");
/* var el='<div>'+ pos.coords.latitude+'</div>';
el+='<div>'+ pos.coords.longitude+'</div>';
el+='<div>'+ pos.timestamp+'</div>';
$('#pagina').html(el);*/
var lat=pos.coords.latitude;
var lon=pos.coords.longitude;
var options={
center:new google.maps.LatLng(lat,lon),
zoom:15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var html=$('#pagina');
console.log(html);
var map= new google.maps.Map(document.getElementById('pagina'),options);
console.log(map);
};
},
onOrientationChange: function() {
if(window.orientation === 0) {
window.history.back();
}
}
});
return LandscapeView;
});
and here the view previous that history.back can't re-call:
var HomeView = Backbone.View.extend({
template: Handlebars.compile(template),
events: {
"click .log_out":"log_out",
"click .prove":"prove",
},
initialize: function() {
console.log("inhomeview");
this.render();
$(window).on('orientationchange', this.onOrientationChange);
},
render: function() {
//var context = JSON.parse(JSON.stringify(this.model));//eliminare
var context=this.model;
var html =this.template(context);
console.log(html);
this.$el.html(html);
$('#pagina').empty();
$('#pagina').append(this.$el.html(html));
return this;
},
onOrientationChange: function() {
if(window.orientation === 90 || window.orientation === -90) {
new LandscapeView();
}
},
log_out:function(){
console.log("logout");
Parse.User.logOut();
// new AppView;//ERRORE UNDEFINED NOT A FUNCTION
window.location='index.html' ;//METTERE UNA NEW APPVIEW MA DA ERRORE!!!
},
prove:function(){
navigator.geolocation.getCurrentPosition(win);
function win(pos){
console.log("gps");
/* var el='<div>'+ pos.coords.latitude+'</div>';
el+='<div>'+ pos.coords.longitude+'</div>';
el+='<div>'+ pos.timestamp+'</div>';
$('#pagina').html(el);*/
var lat=pos.coords.latitude;
var lon=pos.coords.longitude;
var options={
center:new google.maps.LatLng(lat,lon),
zoom:15,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var html=$('#pagina');
console.log(html);
var map= new google.maps.Map(document.getElementById('pagina'),options);
console.log(map);
};
}
});
return HomeView;
});
and this is my router:
var AppRouter = Backbone.Router.extend({
routes: {
"": "home",
"user/:objectId":"prova",
"settings":"settings",//mettere id dell utente loggato
"friends":"friends",
"mailbox":"mailbox"
},
home: function() {
console.log("inrouter");
new AppView();
},
settings: function(){
console.log("settings");
var view=new SettingsView();
$('#pagina').html(view.render().el);
},
friends: function(){
console.log("friends");
var view=new FriendsView();
$('#pagina').html(view.render().el);
} ,
mailbox: function(){
console.log("mailbox");
}
});
return AppRouter;
});
and here the main where the history starts:
document.addEventListener("deviceready", run, false);
run();
function run() {
var sync = Backbone.sync;
Backbone.sync = function(method, model, options) {
options.beforeSend = function (xhr) {
xhr.setRequestHeader('X-Parse-Application-Id', 'qS0KLMx5h9lFLG**yhM9EEPiTS3VMk');
xhr.setRequestHeader('X-Parse-REST-API-Key', 'nh3eoUo9G**vbF2gMhcKJIfIt1Gm');
};
sync(method, model, options);
},
app = new AppRouter();
Backbone.history.start();
Parse.$ = jQuery;
Parse.initialize("qS0KLMx5h9l****tyhM9EEPiTS3VMk",
"H4m*****aGOBqlWzRDW8IrPDpF9qLN7Duy");
}
Related
I put the fetch url with deferred method and I expect it will only invoke the remote ajax request one time.
However, it calls three times when I load the page.
How could I fix it? Thanks
js scripts
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
initialize: function() {
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
this.deferred = new $.Deferred();
},
deferred: Function.constructor.prototype,
fetchSuccess: function(collection, response) {
collection.deferred.resolve();
},
fetchError: function(collection, response) {
throw new Error("Products fetch did get collection from API");
},
var comments = new Comments();
...
comments.deferred.done(function() {
commentView.render();
emptyCommentView.render();
});
compelte js scripts
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
initialize: function() {
this.fetch({
success: this.fetchSuccess,
error: this.fetchError
});
this.deferred = new $.Deferred();
},
deferred: Function.constructor.prototype,
fetchSuccess: function(collection, response) {
collection.deferred.resolve();
},
fetchError: function(collection, response) {
throw new Error("Products fetch did get collection from API");
},
wellFormedComments: function () {
var MESSAGE_LIMIT_LENGTH = 80
var models = comments.select(function (model) {
var msg = model.get("message")
if (msg!=null) {
msg = msg.replace(/^\s+|\s+$/g, '')
if (msg.length >= MESSAGE_LIMIT_LENGTH) {
model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH/2));
} else{
};
return true
}
else{
return false
};
});
return new Comments(models);
},
emptyComments: function () {
var models = comments.select(function (model) {
var msg = model.get("message")
return false===_(msg).notBlank();
});
return new Comments(models);
}
});
var comments = new Comments();
var CommentView = Backbone.View.extend({
el: $("#comments_section"),
render: function() {
var notNullComments = comments.wellFormedComments();
if (notNullComments.length > 0) {
$("#dadasay_comments_plugin").show();
}
var html = commentsTmpl(notNullComments.toJSON());
$(this.el).append(html);
},
});
var EmptyCommentView = Backbone.View.extend({
el: $("#empty_comments_list"),
render: function() {
var source = $('#empty_comments_list_tmpl').html();
var emptyComments = comments.emptyComments();
var html = emptyCommentsTmpl(emptyComments.toJSON());
$(this.el).html(html);
},
});
var commentView = new CommentView({
collection: comments
});
var emptyCommentView = new EmptyCommentView({
collection: comments
});
comments.deferred.done(function() {
commentView.render();
emptyCommentView.render();
});
The problem is that your comments collection triggers fetch when initialized. It's methods wellFormedComments and emptyComments creates new comments collections so they triggers fetch as well.
You can fix this by manually triggering fetch when required, something like:
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
wellFormedComments: function() {
var MESSAGE_LIMIT_LENGTH = 80
var models = this.select(function(model) {
var msg = model.get("message")
if (msg != null) {
msg = msg.replace(/^\s+|\s+$/g, '')
if (msg.length >= MESSAGE_LIMIT_LENGTH) {
model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH / 2));
} else {};
return true
} else {
return false
};
});
return new Comments(models);
},
emptyComments: function() {
var models = this.select(function(model) {
var msg = model.get("message")
return false === _(msg).notBlank();
});
return new Comments(models);
}
});
var CommentView = Backbone.View.extend({
el: $("#comments_section"),
render: function() {
var notNullComments = comments.wellFormedComments();
if (notNullComments.length > 0) {
$("#dadasay_comments_plugin").show();
}
var html = commentsTmpl(notNullComments.toJSON());
$(this.el).append(html);
},
});
var EmptyCommentView = Backbone.View.extend({
el: $("#empty_comments_list"),
render: function() {
var source = $('#empty_comments_list_tmpl').html();
var emptyComments = comments.emptyComments();
var html = emptyCommentsTmpl(emptyComments.toJSON());
$(this.el).html(html);
},
});
var comments = new Comments();
var commentView = new CommentView({
collection: comments
});
var emptyCommentView = new EmptyCommentView({
collection: comments
});
comments.fetch({ // <--------- Do this manually once
success: function() {
commentView.render();
emptyCommentView.render();
},
error: function() {}
});
I think you can better structure your code as shown below, hope the comments explain the changes
var Comments = Backbone.Collection.extend({
model: Comment,
url: fetch_comments_url,
wellFormedComments: function() {
var MESSAGE_LIMIT_LENGTH = 80
var models = this.select(function(model) {
var msg = model.get("message")
if (msg != null) {
msg = msg.replace(/^\s+|\s+$/g, '')
if (msg.length >= MESSAGE_LIMIT_LENGTH) {
model.set("preview_message", msg.substr(0, MESSAGE_LIMIT_LENGTH / 2));
}
return true
}
return false
});
return new Comments(models);
},
emptyComments: function() {
var models = this.select(function(model) {
var msg = model.get("message")
return false === _(msg).notBlank();
});
return new Comments(models);
}
});
var CommentView = Backbone.View.extend({
el: $("#comments_section"),
template: commentsTmpl, // template reference, better create it here
initialize: function() {
this.render(); // self rendering
},
render: function() {
if (this.collection.length) { // use this.collection to refer to view's collection rather than external variables
$("#dadasay_comments_plugin").show(); //This shouldn't be a global selection
}
var html = this.template(this.collection.toJSON());
this.$el.append(html);
//---^ use cached jQuery object rather than creating new one
},
});
var EmptyCommentView = Backbone.View.extend({
el: $("#empty_comments_list"),
template: emptyCommentsTmpl,
initialize: function() {
this.render();
},
render: function() {
var source = $('#empty_comments_list_tmpl').html(); // unused?
var html = this.template(this.collection.toJSON());
this.$el.html(html);
},
});
var comments = new Comments();
comments.fetch({ // <--------- Do this manually once
success: function(collection, response) {
//----------------^ comments collection, all comments
var commentView = new CommentView({
collection: collection.wellFormedComments() // pass the resuting collection
});
var emptyCommentView = new EmptyCommentView({
collection: collection.emptyComments() // pass the resuting collection
});
},
error: function() {}
});
I am new on backbone and using backbone with requirejs to make my first SPA.
When a user navigates to site.com/#report/1 an API call goes to site.com/app/report/1 and collects the data and renders the data in view page. Then, he goes to dashboard and navigates to site.com/#report/2 and another API call collects data of report 2 and displays as well. The problem is when I am using any event handler. In the view page, when anyone clicks on any event, in the callback it says that there is two JSON object saved as model. But it should be the second one only. The first report data also comes in console.log.
For your better understanding, I am giving the code of my router, model and view page.
Router
define([
'backbone',
'models/authlogin',
], function (Backbone, AuthloginModel) {
var AppRouter = Backbone.Router.extend({
routes: {
'': 'renderLoginPage',
'dashboard': 'renderDashBoard',
'report/:id': 'renderReportDetails',
'report/new': 'renderNewReportPage',
'members': 'renderMembersPage',
'member/:id': 'renderMemberPage',
'login': 'renderLoginPage',
'organization': 'renderOrganizationPage',
'programs': 'renderProgramsPage',
'program/:id': 'renderProgramPage',
'*path': 'errorpage'
},
errorpage: function () {
requirejs(['views/404', 'views/dashboard'], function (errorview, DashboardView) {
if ($('nav').length != 1) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
}
new errorview;
});
},
renderLoginPage: function () {
requirejs(['models/auth', 'views/login'], function (AuthModel, LoginView) {
var auth = new AuthModel;
new LoginView({model: auth});
});
},
renderDashBoard: function () {
requirejs([
'collections/reports',
'views/reports',
'views/dashboard',
'../../javascript/main',
], function (ReportsCollection, ReportsView, DashboardView, MainJS) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
var reports = new ReportsCollection;
reports.fetch({wait: true}).then(function () {
new ReportsView({collection: reports});
});
});
},
renderReportDetails: function (page) {
requirejs([
'models/reportdetails',
'views/reportdetails',
'views/dashboard'
], function (ReportDetailsModel, ReportdetailsView, DashboardView) {
var reportdetails = new ReportDetailsModel({id: page});
reportdetails.fetch().then(function () {
if ($('nav').length != 1) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
}
;
new ReportdetailsView({model: reportdetails});
});
});
},
renderNewReportPage: function () {
requirejs([
'collections/newreports',
'views/reports',
'views/newreports',
'../../javascript/main',
], function (ReportsCollection, ReportsView, DashboardView, MainJS) {
})
},
renderMembersPage: function () {
requirejs([
"collections/members",
"collections/invitations",
"views/members",
'views/dashboard'
], function (MembersCollection, InvitationsCollection, MembersView, DashboardView) {
var members = new MembersCollection();
members.fetch().then(function () {
var invitations = new InvitationsCollection();
invitations.fetch().then(function () {
if ($('nav').length != 1) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
}
new MembersView({collection: members, collection2: invitations});
});
});
});
},
renderOrganizationPage: function () {
requirejs([
'models/organization',
'models/orgMembers',
'views/organization',
'views/dashboard'
], function (OrgModel, OrgMembers, OrgView, DashboardView) {
var organization = new OrgModel();
var members = new OrgMembers();
organization.fetch().then(function () {
if ($('nav').length != 1) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
}
members.fetch().then(function () {
new OrgView({model: organization, model2: members});
})
})
});
},
renderProgramsPage: function(){
requirejs([
'collections/programs',
'models/program',
'views/programs',
'views/program',
'views/dashboard'
],function(ProgramsCollection,ProgramsModel,ProgramsView,ProgramView,DashboardView){
var programscollection = new ProgramsCollection;
programscollection.fetch().then(function(){
if ($('nav').length != 1) {
var authlogin = new AuthloginModel;
new DashboardView({model: authlogin});
}
new ProgramsView({collection: programscollection});
});
});
}
});
var initialize = function () {
var app_router = new AppRouter;
Backbone.history.start();
};
return {
initialize: initialize
};
});
Model
define([
'underscore',
'backbone'
],function(_,Backbone){
var ReportDetailsModel = Backbone.Model.extend({
urlRoot: '/app/report/',
idAttribute: 'id'
});
return ReportDetailsModel;
});
View
define([
'backbone',
'../../javascript/magnify_pop_up',
'text!templates/reportdetails.html',
'text!templates/reportcomments.html'
], function (Backbone, Magnify, ReportDetailsTemplate, RepCommentsTemplate) {
var ReportdetailsView = Backbone.View.extend({
el: '#container-2',
template: _.template(ReportDetailsTemplate),
initialize: function () {
this.render();
},
events: {
"click #reject": "reject",
"click #resolve": "resolve",
"click button.triage": "triage"
},
triage: function (e) {
e.preventDefault();
console.log(this.model.toJSON());
/* this.model.save({'status':1},{patch:true,success:function(model,response){
console.log('saved');
},error:function(model,response){
console.log('error');
}});*/
},
resolve: function (e) {
e.preventDefault();
this.model.save({'status':2},{patch:true});
},
reject: function (e) {
e.preventDefault();
this.model.save({'status':3},{patch:true});
},
render: function () {
$('#container').html(this.template(this.model.toJSON()));
this.$el.html(_.template(RepCommentsTemplate)(this.model.toJSON()));
return this;
}
});
return ReportdetailsView;
});
I have a backbone app where the user clicks a button and the a modal is displayed.
On closing the modal I do the following,
$('#myModal').on('hidden.bs.modal', function () {
self.remove();
App.Routes.Application.navigate(App.Routes.Application.previous(), { trigger: true } );
});
The problem is that the modal view is not getting removed, so I click the button to trigger it again, I see 2 modal windows, how can I remove the modal view and then navigate to the route I need?
I have tried ,
$('#myModal').on('hidden.bs.modal', function () {
setTimeout(function() {
self.remove();
}, 500);
App.Routes.Application.navigate(App.Routes.Application.previous(), { trigger: true } );
});
I thought maybe adding a delay between the removal and the navigate would work but nope.
Self is an instance of this view,
App.Views.CreateNewOrganisationView = Backbone.View.extend({
className: 'modal-body',
template: _.template( $('#tpl-new-organisation').html() ),
events: {
"submit .create-organisation" : "createOrganisation",
"click .js-add-member" : "addMember",
"click .js-add-client" : "addClient",
"click .js-add-project" : "addProject",
"click .js-add-team" : "addTeam",
"click .search-results a" : "selectSearchResult",
},
initialize: function() {
this.model = new App.Models.Organisation;
this.render();
},
clean: function() {
console.log("here");
},
render: function() {
//Backbone.Validation.bind(this);
var self = this;
$('#myModal').on('hidden.bs.modal', function () {
setTimeout( function() {
self.remove();
}, 500);
Pops.Routes.Application.navigate(App.Routes.Application.previous(), { trigger: true } );
});
this.$el.html( this.template() ).insertAfter('.modal-header');
this.model.get('members').add(App.Session);
this.model.get('members').first().set({
id: Pops.Session.get('user_id'),
admin: 0
});
var organisationMembersView = new App.Views.GroupsMembersAdminViews({
collection: this.model.get('members')
});
$("#myModal").modal();
return this;
},
addMember: function(e) {
e.preventDefault();
var element = $(e.currentTarget);
this.$('.search').parent().children().show();
this.$('.search').first().remove();
//element.parent().children().hide();
var search = new App.Views.SearchView({
collection: new App.Collections.Users,
type : "users",
merge: false
});
element.parent().prepend(search.render().el);
},
addClient: function(e) {
e.preventDefault();
var element = $(e.currentTarget);
this.$('.search').parent().children().show();
this.$('.search').first().remove();
//element.parent().children().hide();
var search = new Pops.Views.SearchView({
collection: new Pops.Collections.Clients,
type : "clients",
merge: false
});
element.parent().prepend(search.render().el);
},
addProject: function(e) {
e.preventDefault();
var element = $(e.currentTarget);
this.$('.search').parent().children().show();
this.$('.search').first().remove();
//element.parent().children().hide();
var search = new App.Views.SearchView({
collection: new App.Collections.Projects,
type : "projects",
merge: false
});
element.parent().prepend(search.render().el);
},
addTeam: function(e) {
e.preventDefault();
var element = $(e.currentTarget);
this.$('.search').parent().children().show();
this.$('.search').first().remove();
//element.parent().children().hide();
var search = new App.Views.SearchView({
collection: new App.Collections.Teams,
type : "teams",
merge: false
});
element.parent().prepend(search.render().el);
},
selectSearchResult: function(e) {
e.preventDefault();
var element = $(e.currentTarget),
self = this;
switch( element.data('type')) {
case "organisation":
var organisation = new Pops.Models.Organisation({ id: element.data('id')});
organisation.fetch({
success: function() {
self.model.get('organisations').add(organisation);
}
});
break;
case "project":
var project = new App.Models.Project({ id: element.data('id')});
project.fetch({
success: function() {
self.model.get('projects').add(project);
console.log(self.model);
var model = self.model;
self.$('.search').hide();
self.$('button').show();
var projectsDetails = new App.Views.ProjectNamePillView({
model : project
});
self.$('.search').parent().append( projectsDetails.render().el );
self.$('.search').remove();
}
});
break;
// case "workflow":
// break;
case "user":
var member = new App.Models.User({ id: element.data('id')});
member.fetch({
success: function() {
self.model.get('members').add(member);
console.log(self.model);
var model = self.model;
self.$('.search').hide();
self.$('button').show();
var personAvatar = new App.Views.UserInitialsWithAdmin({
model: member
});
self.$('.search').parent().append( personAvatar.render().el);
self.$('.search').remove();
}
});
break;
case "client":
var client = new App.Models.Client({ id: element.data('id')});
client.fetch({
success: function() {
self.model.get('clients').add(client);
var model = self.model;
self.$('.search').hide()
self.$('button').show();
var clientDetails = new App.Views.GroupNameAndAdminsView({
model: client
});
self.$('.search').parent().append( clientDetails.render().el );
self.$('.search').remove();
}
});
break;
case "team":
var team = new App.Models.Team({ id: element.data('id')});
team.fetch({
success: function() {
self.model.get('teams').add(team);
var model = self.model;
self.$('.search').hide()
self.$('button').show();
team.initialize();
var teamDetails = new App.Views.GroupNameAndAdminsView({
model: team
});
self.$('.search').parent().append( teamDetails.render().el );
self.$('.search').remove();
}
});
break;
}
},
remove: function() {
return Backbone.View.prototype.remove.apply(this, arguments);
},
close: function() {
this.unbind();
this.remove();
},
createOrganisation: function(e) {
e.preventDefault();
var element = $(e.currentTarget);
var self = this;
var data = element.serializeJSON();
this.model.save(data, {
success: function() {
if(App.Collections.OrganisationCollection != undefined) {
App.Collections.OrganisationCollection.add(self.model);
}
if(App.Collections._MyOrganisations != undefined) {
App.Collections._MyOrganisations.add(self.model);
}
$("#myModal").modal('hide');
//App.Routes.Application.navigate('#organisations/' . self.model.get())
},
});
}
});
I have such Andularjs code in my app:
angular.module('FlickrMaps', ['SignalR'])
.factory('PhotoMarkers', ['$rootScope', 'Hub', function ($rootScope, Hub) {
var PhotoMarkers = this;
//Hub setup
var hub = new Hub('photos', {
listeners: {
'addTotalPhotosCount': function (total) {
PhotoMarkers.totalCount = total;
$rootScope.$apply();
},
'initPhotoMarker': function (photo) {
var photolocation = new window.google.maps.LatLng(photo.Latitude, photo.Longitude);
var marker = new window.google.maps.Marker({
position: photolocation,
title: photo.Title,
photoThumb: photo.PhotoThumbScr,
photoOriginal: photo.PhotoOriginalScr
});
window.google.maps.event.addListener(marker, 'click', function () {
$rootScope.$broadcast('markerClicked', marker);
});
PhotoMarkers.all.push(marker);
$rootScope.$apply();
},
'photosProcessed': function () {
PhotoMarkers.processedPhotosCount++;
if (PhotoMarkers.processedPhotosCount == PhotoMarkers.totalCount && PhotoMarkers.processedPhotosCount > 0) {
$rootScope.$broadcast('markersLoaded');
}
$rootScope.$apply();
},
},
methods: ['loadRecentPhotos'],
errorHandler: function (error) {
console.error(error);
}
});
//Variables
PhotoMarkers.all = [];
PhotoMarkers.processedPhotosCount = 0;
PhotoMarkers.totalCount = 0;
//Methods
PhotoMarkers.load = function () {
hub.promise.done(function () { //very important!
hub.loadRecentPhotos();
});
};
return PhotoMarkers;
}])
.controller('MapController', ['$scope', 'PhotoMarkers', function ($scope, PhotoMarkers) {
$scope.markers = PhotoMarkers;
$scope.image = '123';
$('#myModal').modal({
backdrop: 'static',
keyboard: false
});
$scope.$on('markerClicked', function (event, data) {
console.log(data.photoThumb);
$scope.omfg = 'nkfglfghlfghflj';
});
$scope.$on('markersLoaded', function () {
$('#myModal').modal('toggle');
$scope.image = 'lol';
var mapOptions = {
zoom: 4,
center: new window.google.maps.LatLng(40.0000, -98.0000),
mapTypeId: window.google.maps.MapTypeId.TERRAIN
};
console.log(PhotoMarkers.all);
$scope.map = new window.google.maps.Map(document.getElementById('map-canvas'), mapOptions);
var markerCluster = new MarkerClusterer($scope.map, $scope.markers.all);
});
}])
$broadcast and $on services work finem but when I try to change $scope.image variable on markerClicked event it doesn't change on view page, but for markersLoaded it changes. Does anyone have any ideas? I tried lot of ways to fix it...
You need to wrap it inside $apply since you are in a callback outside angular:
window.google.maps.event.addListener(marker, 'click', function () {
$rootScope.$apply(function() {
$rootScope.$broadcast('markerClicked', marker);
});
});
I know Im pretty close to figuring this out. Im trying to filter out my collection based on if favorite eq true. If I console.log - I can see it's doing its job. But it's not updating my view.
Anyone have any idea what I'm missing or doing wrong?
Here is my code:
var Products = Backbone.Model.extend({
// Set default values.
defaults: {
favorite: false
}
});
var ProductListCollection = Backbone.Collection.extend({
model: Products,
url: '/js/data/wine_list.json',
parse: function(data) {
return data;
},
comparator: function(products) {
return products.get('Vintage');
},
favoritesFilter1: function(favorite) {
return this.filter(function(products) {
return products.get('favorite') == true;
});
},
favoritesFilter: function() {
return this.filter(function(products) {
return products.get('favorite') == true;
});
},
});
var products = new ProductListCollection();
var ProductListItemView = Backbone.View.extend({
el: '#wine-cellar-list',
initialize: function() {
products.bind('reset', this.render, this);
products.fetch();
this.render();
},
render: function() {
console.log(this.collection);
var source = $('#product-template').html();
var template = Handlebars.compile(source);
var html = template(this.collection.toJSON());
this.$el.html(html);
return this;
},
});
// Create instances of the views
var productView = new ProductListItemView({
collection: products
});
var CellarRouter = Backbone.Router.extend({
routes: {
'': 'default',
"favorites": "showFavorites",
"purchased": "showPurchased",
"top-rated": "showTopRated",
},
default: function() {
productView.render();
},
showFavorites: function() {
console.log('Favorites');
productView.initialize(products.favoritesFilter());
},
showPurchased: function() {
console.log('Purchased');
},
showTopRated: function() {
console.log('Top Rated');
}
});
$(function() {
var myCellarRouter = new CellarRouter();
Backbone.history.start();
});
There's many mistakes in your code, I'll try to clarify the most I can :
Your collection should be just like this :
var ProductListCollection = Backbone.Collection.extend({
model: Products,
url: '/js/data/wine_list.json',
comparator: 'Vintage' // I guess you want to sort by this field
});
Your view like this :
var ProductListItemView = Backbone.View.extend({
el: '#wine-cellar-list',
initialize: function() {
this.collection.bind('reset', this.full, this);
this.collection.fetch();
},
full: function() {
this.render(this.collection.models);
},
favorites: function(favorite) {
this.render(this.collection.where(favorite)); // here's the answer to your question
},
render: function(models) {
console.log(models);
var source = $('#product-template').html();
var template = Handlebars.compile(source);
var html = template(models.toJSON()); // You may have to change this line
this.$el.html(html);
return this;
},
});
And in your router :
showFavorites: function() {
console.log('Favorites');
productView.favorites(true); // or false, as you like
}