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();
});
Related
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 ().
I'm starting to learn and azure phonejs.
Todo list get through a standard example:
$(function() {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
// Read current data and rebuild UI.
// If you plan to generate complex UIs like this, consider using a JavaScript templating library.
function refreshTodoItems() {
var query = todoItemTable.where({ complete: false });
query.read().then(function(todoItems) {
var listItems = $.map(todoItems, function(item) {
return $('<li>')
.attr('data-todoitem-id', item.id)
.append($('<button class="item-delete">Delete</button>'))
.append($('<input type="checkbox" class="item-complete">').prop('checked', item.complete))
.append($('<div>').append($('<input class="item-text">').val(item.text)));
});
$('#todo-items').empty().append(listItems).toggle(listItems.length > 0);
$('#summary').html('<strong>' + todoItems.length + '</strong> item(s)');
}, handleError);
}
function handleError(error) {
var text = error + (error.request ? ' - ' + error.request.status : '');
$('#errorlog').append($('<li>').text(text));
}
function getTodoItemId(formElement) {
return $(formElement).closest('li').attr('data-todoitem-id');
}
// Handle insert
$('#add-item').submit(function(evt) {
var textbox = $('#new-item-text'),
itemText = textbox.val();
if (itemText !== '') {
todoItemTable.insert({ text: itemText, complete: false }).then(refreshTodoItems, handleError);
}
textbox.val('').focus();
evt.preventDefault();
});
// Handle update
$(document.body).on('change', '.item-text', function() {
var newText = $(this).val();
todoItemTable.update({ id: getTodoItemId(this), text: newText }).then(null, handleError);
});
$(document.body).on('change', '.item-complete', function() {
var isComplete = $(this).prop('checked');
todoItemTable.update({ id: getTodoItemId(this), complete: isComplete }).then(refreshTodoItems, handleError);
});
// Handle delete
$(document.body).on('click', '.item-delete', function () {
todoItemTable.del({ id: getTodoItemId(this) }).then(refreshTodoItems, handleError);
});
// On initial load, start by fetching the current data
refreshTodoItems();
});
and it works!
Changed for the use of phonejs and the program stops working, even mistakes does not issue!
This my View:
<div data-options="dxView : { name: 'home', title: 'Home' } " >
<div class="home-view" data-options="dxContent : { targetPlaceholder: 'content' } " >
<button data-bind="click: incrementClickCounter">Click me</button>
<span data-bind="text: listData"></span>
<div data-bind="dxList:{
dataSource: listData,
itemTemplate:'toDoItemTemplate'}">
<div data-options="dxTemplate:{ name:'toDoItemTemplate' }">
<div style="float:left; width:100%;">
<h1 data-bind="text: name"></h1>
</div>
</div>
</div>
</div>
This my ViewModel:
Application1.home = function (params) {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
var toDoArray = ko.observableArray([
{ name: "111", type: "111" },
{ name: "222", type: "222" }]);
var query = todoItemTable.where({ complete: false });
query.read().then(function (todoItems) {
for (var i = 0; i < todoItems.length; i++) {
toDoArray.push({ name: todoItems[i].text, type: "NEW!" });
}
});
var viewModel = {
listData: toDoArray,
incrementClickCounter: function () {
todoItemTable = client.getTable('todoitem');
toDoArray.push({ name: "Zippy", type: "Unknown" });
}
};
return viewModel;
};
I can easily add items to the list of programs, but from the server list does not come:-(
I am driven to exhaustion and can not solve the problem for 3 days, which is critical for me!
Specify where my mistake! Thank U!
I suggest you use a DevExpress.data.DataSource and a DevExpress.data.CustomStore instead of ko.observableArray.
Application1.home = function (params) {
var client = new WindowsAzure.MobileServiceClient('https://zaburrito.azure-mobile.net/', 'key');
var todoItemTable = client.getTable('todoitem');
var toDoArray = [];
var store = new DevExpress.data.CustomStore({
load: function(loadOptions) {
var d = $.Deferred();
if(toDoArray.length) {
d.resolve(toDoArray);
} else {
todoItemTable
.where({ complete: false })
.read()
.then(function(todoItems) {
for (var i = 0; i < todoItems.length; i++) {
toDoArray.push({ name: todoItems[i].text, type: "NEW!" });
}
d.resolve(toDoArray);
});
}
return d.promise();
},
insert: function(values) {
return toDoArray.push(values) - 1;
},
remove: function(key) {
if (!(key in toDoArray))
throw Error("Unknown key");
toDoArray.splice(key, 1);
},
update: function(key, values) {
if (!(key in toDoArray))
throw Error("Unknown key");
toDoArray[key] = $.extend(true, toDoArray[key], values);
}
});
var source = new DevExpress.data.DataSource(store);
// older version
store.modified.add(function() { source.load(); });
// starting from 14.2:
// store.on("modified", function() { source.load(); });
var viewModel = {
listData: source,
incrementClickCounter: function () {
store.insert({ name: "Zippy", type: "Unknown" });
}
};
return viewModel;
}
You can read more about it here and here.
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 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
}