I'm trying to create a module using Backbone.js, but I'm getting the error Javascript Error: Uncaught TypeError: autoAuth.View is not a constructor.
Auth.js.erb
(function(app, Auth){
var game = app.module('game');
Auth.View = Backbone.View.extend({
el: '.js-auth',
cssClass: 'auth',
events: {
'click .js-popup': 'popupLogin',
'click .js-login-with-email': 'emailLogin',
'click .js-tos-modal': 'tosModal',
'click .js-privacy-modal': 'privacyModal',
'click .js-auto-login': 'autoLogin'
},
template: Handlebars.compile(
<%= embed('../templates/auth.hbs').inspect %>
),
initialize: function() {
Handlebars.registerPartial('login-buttons',
<%= embed('../templates/login-buttons.hbs').inspect %>
);
},
render: function() {
_.extend(this.options, {
skipOnboarding: game.player.get('skip_onboarding'),
claimableIncentive: game.incentive.get('claimable'),
claimableAmount: game.incentive.get('amount'),
});
this.$el.addClass(this.cssClass);
this.$el.html(this.template(this.options));
growth.urlChangeNotification();
},
popupLogin: function(event) {
event.preventDefault();
event.stopPropagation();
this.validateLogin(_.partial(popupLogin, event));
},
emailLogin: function(event) {
this.validateLogin(_.partial(this.emailAuth, event));
},
autoLogin: function(event) {
this.validateLogin(_.partial(this.autoAuth, event));
},
validateLogin: function(callback) {
if (this.$el.find('#agree-to-tos').is(':checked')) {
callback();
} else {
this.$el.find('.js-tos-error').show();
}
},
emailAuth: function(view_option, value) {
var emailAuth = app.module('emailAuth');
var emailAuthView = new emailAuth.View;
if (_.isString(view_option)) {
emailAuthView.setViewOption(view_option);
if (view_option === 'reset') {
game.user.set('reset_password_token', value);
}
}
emailAuthView.openModal({
allowCancel: view_option !== 'reset'
});
emailAuthView.render();
},
autoAuth: function(view_option, value) {
var autoAuth = app.module('autoAuth');
var autoAuthView = new autoAuth.View;
if (_.isString(view_option)) {
autoAuthView.setViewOption(view_option);
}
autoAuthView.openModal({
allowCancel: view_option !== 'reset'
});
autoAuthView.render();
},
tosModal: function() {
var modal = new Backbone.BootstrapModal({
content: <%= embed('../templates/terms-of-service.hbs').inspect %>
}).open();
},
privacyModal: function() {
var modal = new Backbone.BootstrapModal({
content: <%= embed('../templates/privacy-policy.hbs').inspect %>
}).open();
}
});
})(app, app.module('auth'));
AutoAuth.js.erb
function(app, AutoAuth)(
var game = app.module('game');
AutoAuth.View = ModalView.extend({
view_modes: ['login'],
template: Handlebars.compile(
<%= embed('../templates/auto-auth.hbs').inspect %>
),
events: {
'submit #email-login': 'logIn',
'click #login': function() {
this.setViewOption('login');
this.render();
},
},
genericErrorMessage: 'Oops something went wrong! Please contact support.',
initialize: function(options) {
var self = this;
this.options = options || {};
this.setViewOption('login');
_.bindAl(this, 'login');
game.user.on({
signin_sucess: function(){
self.reloadPage();
},
signin_error: function(data) {
self.options.error = false;
self.setViewOption('login');
var error = 'Unable to sign in with the given email and password.';
if (data && data.error) { error = data.error; }
self.options.signin_error = error;
self.render();
},
})
},
setViewOption: function(view) {
var self = this;
_.each(self.view_modes, function(k) {
self.options[k] = false;
});
self.options[view] = true;
},
render: function(){
this.$el.html(this.template(this.options));
if (mobile) window.scrollTo(0, 1); // hack for modals on mobile
this.delegateEvents();
this.clearErrors();
var authPage = _.chain(this.options)
.pick(function(value, key) { return value; })
.keys()
.value()[0];
growth.urlChangeNotification();
},
logIn: function(e) {
e.preventDefault();
this.options.email = this.$('#login_email').val();
if (!validateEmail(this.options.email)) {
this.options.signin_error = 'Must enter a valid email address.';
this.render();
return;
}
game.user.signIn({
email: this.options.email,
password: this.$('#login_password').val(),
remember_me: true
});
},
reloadPage: function() {
window.location = window.location.href.substr(0, window.location.href.indexOf('#'));
}
});
})(app, app.module('authAuth'));
Do you have this error on the line with var autoAuthView = new autoAuth.View; ?
To create a new instance of autoAuth.View you need to do var autoAuthView = new autoAuth.View();.
autoAuth.View is the class, to call the contructor, and create a new instance, you need to call it with ().
Related
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 want to build a simple backbone app for depositing and withdrawing funds via Stripe. Since a lot of the functionality is common, I placed that in a Stripe view, and extend the Deposit and Withdraw views from it, like so:
var App = {
Models: {},
Collections: {},
Views: {},
Router: {}
}
App.Views.Home = Backbone.View.extend({
el: $('#main-content'),
template: Handlebars.compile($('#home-template').html()),
render: function() {
this.$el.html(this.template())
return this
},
events: {
'click #deposit-button': 'navigateToDeposit',
'click #withdraw-button': 'navigateToWithdraw'
},
navigateToDeposit: function(e) {
Backbone.history.navigate('/deposit', true)
},
navigateToWithdraw: function(e) {
Backbone.history.navigate('/withdraw', true)
}
})
App.Views.Stripe = Backbone.View.extend({
el: $('#main-content'),
initialize: function() {
Stripe.setPublishableKey('pk_test_0QvQdPBkXAjB4EBsT4mf226x')
},
render: function() {
this.$el.html(this.template())
return this
},
events: {
'click #submit': 'submitForm'
},
submitForm: function(e) {
e.preventDefault()
$('#submit').prop('disabled', true)
var that = this
Stripe.card.createToken($('#form'), that.stripeResponseHandler)
},
stripeResponseHandler: function(status, response) {
var $form = $('#form')
if(response.error) {
$form.find('.payment-errors').text(response.error.message)
$('submit').prop('disabled', false)
} else {
console.log(this)
var form_data = this.getFormData(response.id),
that = this
$.post(that.transaction_endpoint, form_data, function(data, textStatus, jqXHR) {
Backbone.history.navigate('/home', true)
})
}
}
})
App.Views.Deposit = App.Views.Stripe.extend({
template: Handlebars.compile($('#deposit-template').html()),
getFormData: function(token) {
return {
amount: $('#form input[name=amount]').val(),
token: token
}
},
transaction_endpoint: 'handledeposit'
})
App.Views.Withdraw = App.Views.Stripe.extend({
template: Handlebars.compile($('#withdraw-template').html()),
getFormData: function(token) {
return {
name: $('#form input[name=name]').val(),
email: $('#form input[name=email]').val(),
token: token
}
},
transaction_endpoint: 'handlewithdraw'
})
App.Router = Backbone.Router.extend({
routes: {
'deposit' : 'showDepositView',
'withdraw' : 'showWithdrawView',
'*path' : 'showHomeView'
},
showDepositView: function() {
var depositView = new App.Views.Deposit()
depositView.render()
},
showWithdrawView: function() {
var withdrawView = new App.Views.Withdraw()
withdrawView.render()
},
showHomeView: function() {
var homeView = new App.Views.Home()
homeView.render()
}
})
var router = new App.Router()
Backbone.history.start()
The call to the getFormData method gives me an error saying the function is undefined, even though I have defined it in both Deposit and Withdraw views. Also, I added a console.log(this) right above it, and it logs the Window object to the console instead of the View. What am I doing wrong here?
I have a feeling it's to do with this call:
Stripe.card.createToken($('#form'), that.stripeResponseHandler)
Try binding this to the calling scope using .bind():
Stripe.card.createToken($('#form'), that.stripeResponseHandler.bind(this))
You don't really need to do var that = this but I'll leave it in for simplicity's sake.
I need to close the current region in the method onRender and display a different region. But after a run operator 'return' I see again the old region.
Please tell me what is my mistake.
ApplicationPageLayout = Backbone.Marionette.Layout.extend({
template: "#application-page-layout-template",
regions: {
footerRegion: "#footer",
navigationRegion: "#navigation",
contentRegion: "#content"
},
onRender: function() {
if (this.options.postName) {
var footerData = {};
switch (this.options.postName) {
case "Admin":
this.footerRegion.show(new AdminFooterView());
break;
case "Dispatcher":
this.footerRegion.show(new DispatcherFooterView());
break;
default:
debugger; // See current region.
MainApplication.mainRegion.show(new LoginPageLayout(), { preventDestroy: true });
debugger; // See new region LoginPageLayout.
return; // Again see old region.
}
}
}
});
Ishow all code:
/**
* Main javaScript file.
*/
MainApplication = new Backbone.Marionette.Application();
LoginPageLayout = Backbone.Marionette.Layout.extend({
template: "#login-page-layout-template",
regions: {
authorizationFormRegion: "#login-form-wrapper",
errorRegion: "#login-message-wrapper"
},
// Show login form.
onRender: function () {
this.loginFormView = new LoginFormView();
this.authorizationFormRegion.show(this.loginFormView);
},
events: {
"click #login-button": "login"
},
login: function () {
var httpParameters = {pin: this.loginFormView.ui.pinCodeField.val()};
var thisLayout = this;
$.ajax({
url: '../autorisation',
type: 'POST',
data: httpParameters,
success: function(data) {
if (data.isSuccessfully) {
MainApplication.mainRegion.show(new ApplicationPageLayout(data), { preventDestroy: true });
} else {
var textMessageModel = new Backbone.Model({
message: "Ошибка. Учетная запись не найдена."
});
var loginMessageView = new LoginMessageView({
model: textMessageModel
});
thisLayout.errorRegion.show(loginMessageView);
}
},
error: function(data) {
alert("Сервер временно недоступен.");
}
});
return false;
}
});
ApplicationPageLayout = Backbone.Marionette.Layout.extend({
template: "#application-page-layout-template",
regions: {
footerRegion: "#footer",
navigationRegion: "#navigation",
contentRegion: "#content"
},
onRender: function() {
if (this.options.postName) {
var footerData = {};
switch (this.options.postName) {
case "Диспетчер":
this.footerRegion.show(new DispatcherFooterView());
break;
case "Администратор":
footerData.title = "Панель aдминитратора";
break;
default:
this.close();
}
}
}
});
FooterView = Backbone.Marionette.ItemView.extend({
regions: {
staffLogo: "#staff-logo"
},
ui: {
staffLogo: "#staff-logo"
}
});
DispatcherFooterView = FooterView.extend({
template: "#dispatcher-footer-template",
events: {
"click #dispatcher-logo": "showAlerts"
}
});
LoginFormView = Backbone.Marionette.ItemView.extend({
template: "#login-form-template",
ui: {
loginButton: "#login-button",
pinCodeField: "#login-pin"
}
});
LoginMessageView = Backbone.Marionette.ItemView.extend({
template: "#login-message-template"
});
MainApplication.addInitializer(function(options) {
MainApplication.addRegions({
mainRegion: "#mainRegion"
});
MainApplication.mainRegion.show(new LoginPageLayout());
});
$(function() {
MainApplication.start();
});
I'm trying to store my models into local storage using backone.localStorage. Unfortunately nothing gets stored.
As for as I understand the collection needs only one line
localStorage: new Backbone.LocalStorage("days")
but that doesn't help. If I check the localStorage using Chrome dev tools nothing is stored.
This is my code:
// Filename: app.js
define([
'jquery',
'underscore',
'backbone',
'localStorage'
], function($, _, Backbone){
var initialize = function(){
(function ($) {
var Day = Backbone.Model.extend({
initialize: function() {
this.on("change", this.calculateWorkTime);
this.calculateWorkTime();
},
defaults: {
"date": new Date(),
"fromAm": 0,
"toAm": 0,
"fromPm": 0,
"toPm": 0,
"workTime": 0
},
isValidTime: function(n) {
return !isNaN(parseFloat(n)) && isFinite(n) && parseFloat(n)>0;
},
calculateWorkTime: function() {
var work = 0.0;
if (timeToFloat(this.get("fromAm")) < timeToFloat(this.get("toAm")) ) {
work += timeToFloat(this.get("toAm")) - timeToFloat(this.get("fromAm"));
}
if (timeToFloat(this.get("fromPm")) < timeToFloat(this.get("toPm")) ) {
work += timeToFloat(this.get("toPm")) - timeToFloat(this.get("fromPm"));
}
this.set("workTime", floatToTime(work));
}
});
var DayList = Backbone.Collection.extend({
model: Day,
localStorage: new Backbone.LocalStorage("days")
});
var DataRow = Backbone.View.extend({
tagName: "tr",
template: _.template($('#table-row-day').html()),
events: {
"change .edit-field": "updateModel",
"click #button-delete-day": "deleteDay"
},
initialize: function() {
this.listenTo(this.model, 'destroy', this.remove);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
updateModel: function(event) {
var myValue = "leer";
switch (event.currentTarget.id) {
case "table-edit-date":
myValue = this.$('#table-edit-date').val();
this.model.set("date", myValue);
break;
case "table-edit-fromAm":
myValue = this.$('#table-edit-fromAm').val();
this.model.set("fromAm", myValue);
break;
case "table-edit-toAm":
myValue = this.$('#table-edit-toAm').val();
this.model.set("toAm", myValue);
break;
case "table-edit-fromPm":
myValue = this.$('#table-edit-fromPm').val();
this.model.set("fromPm", myValue);
break;
case "table-edit-toPm":
myValue = this.$('#table-edit-toPm').val();
this.model.set("toPm", myValue);
break;
}
this.render();
console.log(this.model.toJSON());
},
deleteDay: function(a, b, c, d) {
this.model.destroy();
}
});
var Days = new DayList;
AppView = Backbone.View.extend({
el: $("body"),
initialize: function () {
this.listenTo(Days, 'add', this.addOne);
this.listenTo(Days, 'all', this.refreshTotal);
this.total = this.$("#total-work");
Days.fetch();
this.refreshTotal();
},
events: {
"click #button-add-day": "addDay"
},
addDay: function () {
var day = new Day({
"date": $("#form-add-date").val(),
"fromAm": $("#form-add-fromAm").val(),
"toAm": $("#form-add-toAm").val(),
"fromPm": $("#form-add-fromPm").val(),
"toPm": $("#form-add-toPm").val()
});
Days.add(day);
},
addOne: function(day) {
var view = new DataRow({model: day});
this.$("#table-body-days").append(view.render().el);
},
refreshTotal: function() {
var work = 0;
Days.each(function($i) {
work += timeToFloat($i.get("workTime"));
});
this.total.html(floatToTime(work));
}
});
function timeToFloat(time) {
var parts = time.split(":");
if (parts.length<2) return 0.0;
return parseFloat(parts[0])+parseFloat(parts[1])/60;
}
function floatToTime(floatValue) {
var fraction = floatValue - Math.floor(floatValue);
var whole = Math.floor(floatValue);
return whole+":"+Math.round(fraction*60.0);
}
var appview = new AppView;
})($);
};
return {
initialize: initialize
};
});
As the comment points out the calls to save are missing. I added them to DataRow.updateModel() and AppView.addDay().
This is the correct code:
// Filename: app.js
define([
'jquery',
'underscore',
'backbone',
'localStorage'
], function($, _, Backbone){
var initialize = function(){
(function ($) {
var Day = Backbone.Model.extend({
initialize: function() {
this.on("change", this.calculateWorkTime);
this.calculateWorkTime();
},
defaults: {
"date": new Date(),
"fromAm": 0,
"toAm": 0,
"fromPm": 0,
"toPm": 0,
"workTime": 0
},
isValidTime: function(n) {
return !isNaN(parseFloat(n)) && isFinite(n) && parseFloat(n)>0;
},
calculateWorkTime: function() {
var work = 0.0;
if (timeToFloat(this.get("fromAm")) < timeToFloat(this.get("toAm")) ) {
work += timeToFloat(this.get("toAm")) - timeToFloat(this.get("fromAm"));
}
if (timeToFloat(this.get("fromPm")) < timeToFloat(this.get("toPm")) ) {
work += timeToFloat(this.get("toPm")) - timeToFloat(this.get("fromPm"));
}
this.set("workTime", floatToTime(work));
}
});
var DayList = Backbone.Collection.extend({
model: Day,
localStorage: new Backbone.LocalStorage("days")
});
var DataRow = Backbone.View.extend({
tagName: "tr",
template: _.template($('#table-row-day').html()),
events: {
"change .edit-field": "updateModel",
"click #button-delete-day": "deleteDay"
},
initialize: function() {
this.listenTo(this.model, 'destroy', this.remove);
},
render: function() {
this.$el.html(this.template(this.model.toJSON()));
return this;
},
updateModel: function(event) {
var myValue = "leer";
switch (event.currentTarget.id) {
case "table-edit-date":
myValue = this.$('#table-edit-date').val();
this.model.set("date", myValue);
break;
case "table-edit-fromAm":
myValue = this.$('#table-edit-fromAm').val();
this.model.set("fromAm", myValue);
break;
case "table-edit-toAm":
myValue = this.$('#table-edit-toAm').val();
this.model.set("toAm", myValue);
break;
case "table-edit-fromPm":
myValue = this.$('#table-edit-fromPm').val();
this.model.set("fromPm", myValue);
break;
case "table-edit-toPm":
myValue = this.$('#table-edit-toPm').val();
this.model.set("toPm", myValue);
break;
}
this.model.save();
this.render();
console.log(this.model.toJSON());
},
deleteDay: function(a, b, c, d) {
this.model.destroy();
}
});
var Days = new DayList;
AppView = Backbone.View.extend({
el: $("body"),
initialize: function () {
this.listenTo(Days, 'add', this.addOne);
this.listenTo(Days, 'all', this.refreshTotal);
this.total = this.$("#total-work");
Days.fetch();
this.refreshTotal();
},
events: {
"click #button-add-day": "addDay"
},
addDay: function () {
var day = new Day({
"date": $("#form-add-date").val(),
"fromAm": $("#form-add-fromAm").val(),
"toAm": $("#form-add-toAm").val(),
"fromPm": $("#form-add-fromPm").val(),
"toPm": $("#form-add-toPm").val()
});
Days.add(day);
day.save();
},
addOne: function(day) {
var view = new DataRow({model: day});
this.$("#table-body-days").append(view.render().el);
},
refreshTotal: function() {
var work = 0;
Days.each(function($i) {
work += timeToFloat($i.get("workTime"));
});
this.total.html(floatToTime(work));
}
});
function timeToFloat(time) {
var parts = time.split(":");
if (parts.length<2) return 0.0;
return parseFloat(parts[0])+parseFloat(parts[1])/60;
}
function floatToTime(floatValue) {
var fraction = floatValue - Math.floor(floatValue);
var whole = Math.floor(floatValue);
return whole+":"+Math.round(fraction*60.0);
}
var appview = new AppView;
})($);
};
return {
initialize: initialize
};
});
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
}