Backbone collection fetch not firing - javascript

I'm new to backbone and I'm trying to send and receive data from the server in Json format. It just won't work. Here's my code (BTW, I'm using backbone aura):
Collection
define(['sandbox', '../models/message'], function(sandbox, Message) {
'use strict';
var Messages = sandbox.mvc.Collection({
model: Message,
url: '/messagelist.php',
localStorage: new sandbox.data.Store('messages-backbone-require'),
parse: function(response){
return response.rows;
}
});
return Messages;
});
Model
define(['sandbox'], function(sandbox) {
'use strict';
var Message = sandbox.mvc.Model({
defaults: {
opened: '',
messageid: '',
phonenumber: '',
numbername: '',
text: ''
},
parse: function(data){
return data;
}
});
return Message;
});
View
define(['sandbox', '../models/message', 'text!../templates/incoming_messages.html'], function(sandbox, Message, incomingMessagesTemplate) {
'use strict';
var AppView = sandbox.mvc.View({
widgetTemplate: sandbox.template.parse(incomingMessagesTemplate),
events: {
'click .refresh': 'refresh'
},
initialize: function() {
this.$el.html(this.widgetTemplate);
sandbox.events.bindAll(this);
this.collection.bind('createMessageList', this.createMessageList);
},
createMessageList: function() {
// Will work with the received data here
},
render: function() {
var handle = 'h4';
this.$el.draggable({handle: handle});
this.createMessageList();
},
refresh: function() {
this.createMessageList();
}
});
return AppView;
});
Main
define(['sandbox', './views/app', './collections/messages'], function(sandbox, AppView, Messages) {
'use strict';
return function(options) {
var messages = new Messages();
new AppView({
el: sandbox.dom.find(options.element),
collection: messages
}).render();
messages.fetch({
data: {
type: 'incoming',
offset: 0,
offsetcount: 25
},
type: 'GET',
success: function() {
console.log(messages.models); // Shows an empty array.
}
});
};
});
I've check logs and it seems that the ajax request (collection.fetch()) is not firing or is not able to communicate with the server. How can I fix this?

The problem is with the Backbone.LocalStorage plugin. When you assign Collection.localStorage, the plugin takes over the fetch command and reads the data from local storage instead of the server.
See my answer in this SO question on some options on how to solve this.

Related

RequireJS modules are undefined in Backbone view

I have been pretty much beginner at this part of javascript and I would appreciate any ideas how could be solved this problem.
I use requirejs to define my own modules where I also use backbone.js.
Let say I have the main module where I initialize my Backbone view which is rendered without any problem. Also, the click event where is calling method createSchemeForm creates the form correctly. The problem raises up in a situation when I call cancel method by click and the modules which are defined for Backbone view (e.g. "unicorn/sla/dom/helper"...) are undefined but when I called method createSchemeForm at the beginning the modules were executed without any problem.
Thank you in advance for any suggestions.
Backbone view
define("unicorn/sla/view/scheme", [
"unicorn/sla/dom/helper",
"unicorn/soy/utils",
"unicorn/sla/utils"
], function (DOMHelper, soyUtils, jsUtils) {
return Backbone.View.extend({
el: 'body',
inputData: {},
btnSaveScheme: 'btn-save-sla-scheme',
btnCancel: 'btn-cancel-sla-scheme',
btnCreate: 'btn-create-sla-scheme',
btnContainer: '#sla-scheme-buttons-container',
schemeContent: '#sla-scheme-content-section',
btnSpinner: '.button-spinner',
events: {
'click #btn-create-sla-scheme' : "createSchemeForm",
'click #btn-cancel-sla-scheme' : "cancel"
},
initialize: function(){
console.log("The scheme view is initialized...");
this.render();
},
createSchemeForm: function () {
this.spin();
DOMHelper.clearSchemeContent();
DOMHelper.clearButtonsContainer();
//Get button
$btnSave = soyUtils.getButton({isPrimary: 'true', id: this.btnSaveScheme, label: 'Save'});
$btnCancel = soyUtils.getButton({isPrimary: 'false', id: this.btnCancel, label: 'Cancel'});
//Append new created buttons
DOMHelper.addContent(this.btnContainer, AJS.format("{0}{1}", $btnSave, $btnCancel));
//Call service to get entry data for scheme creation form
AJS.$.ajax({
url: AJS.format('{0}={1}',AJS.I18n.getText('rest-url-project-scheme-input-data'), jsUtils.getProjectKey()) ,
type: "post",
async: false,
context: this,
global: false,
}).done(function (data) {
this.inputData = data;
$slaSchemeForm = soyUtils.getSchemeCreateForm({slaScheme : data, helpText: AJS.I18n.getText("sla-time-target-tooltip-text")});
DOMHelper.addContent(this.schemeContent, $slaSchemeForm);
jsUtils.scroll(this.schemeContent, 'slow');
}).fail(function () {
jsUtils.callFlag('error', AJS.I18n.getText("message-title-error"), AJS.I18n.getText("sla-error-load-scheme-input-data"));
}).always(function () {
this.stopSpin();
});
},
spin: function () {
AJS.$('.button-spinner').spin();
},
stopSpin: function () {
AJS.$('.button-spinner').spinStop();
},
cancel: function () {
jsUtils.clearButtonsContainer();
jsUtils.clearSchemeContent();
$btnCreateScheme = soyUtils.getButton({isPrimary: 'false', id: this.btnCreate, label: 'Create SLA Scheme'});
DOMHelper.addContent(this.btnContainer, $btnCreateScheme);
DOMHelper.addContent(this.schemeContent, soyUtils.getSchemesTable(new Array())); // TODO - get current data from server instead of empty array
}
});
});
Main module where is Backbone view initialize
define("unicorn/sla/project/batch", [
"unicorn/sla/utils",
"unicorn/sla/data/operations",
"unicorn/sla/data/validator",
"unicorn/sla/dom/helper",
"unicorn/sla/model/confirm/message",
"unicorn/sla/view/scheme",
"exports"
], function (jsUtils, operations, validator, DOMHelper, ConfirmMessage, SchemeView, exports) {
//Load project batch
exports.onReady = function () {
$schemeView = new SchemeView();
$schemeView.render();
}
});
AJS.$(function () {
AJS.$(document).ready(function () {
require("unicorn/sla/project/batch").onReady();
});
});

Backbone fetch producing 404 error

I have the following backbone model node that I am trying to use to fetch data from the server but at the moment I get a 404 error, I have checked my files and they seem to be correct
var app = app || {};
app.NotesModel = Backbone.Model.extend({
url:'/usernotes',
defaults: {
username:'',
email:'',
about:'',
editorNote:''
}
});
app.NotesView = Backbone.View.extend({
el:'#notes',
events: {
'click #save': 'save'
},
template1: _.template($('#about').html()),
template2: _.template($('#facts').html()),
initialize: function() {
app.NotesModel = new app.NotesModel({});
var email = $('#data-user').text();
app.NotesModel.fetch({data: {email: email},type:'GET' });
this.render();
},
render: function() {
},
This is what the route file looks like
app.get('/account/usernotes/', require('./views/account/usernotes/index').init);
app.get('/account/usernotes/:email', require('./views/account/usernotes/index').find);
and the functions for the routes
'use strict';
exports.init = function(req, res){
if (req.isAuthenticated()) {
//console.log(req.user.email);
res.render('account/usernotes',
{ data : {
user : req.user.email
}
});
}
else {
res.render('signup/index', {
oauthMessage: '',
oauthTwitter: !!req.app.config.oauth.twitter.key,
oauthFacebook: !!req.app.config.oauth.facebook.key,
oauthGoogle: !!req.app.config.oauth.google.key
});
}
};
exports.find = function(req,res) {
console.log('here');
console.log(JSON.stringify(req));
}
Doing the console.log() doesn't give me any output at all.
Here is a similar question.
Try this:
app.NotesModel.fetch({data: $.param({email: email}) });
or this:
app.NotesModel.fetch({data: {email: email}, processData: true });

Backbone.js manually trigger "error" on a collection

I want my collection to fail if the server/json return a specific STATUS (e.g. no results).
The problem: The default error-handler is not called (cause the collection successfully fetches the json. So my idea is use the parse function to look for an error-code in the json.
But how to I trigger the error-method and notify my view (and stop to collection trying to create models)
/*global define*/
define([
'underscore',
'backbone',
'models/mymodel'
], function (_, Backbone, MyModel) {
'use strict';
var SomeCollection = Backbone.Collection.extend({
model: MyModel,
value: null,
url: function() {
return url: "data/list.json";
},
initialize: function(models, options) {
this.zipcode = options.zipcode;
},
parse: function(response, xhr) {
if(response.status == "OK") {
console.info("Status: "+response.status);
return response.results;
} else {
console.warn("Status: "+response.status+" – Message: "+response.message);
this.trigger('fail') // does not work
return response;
}
}
});
return SomeCollection;
});
I have a post on my blog about this kind of things, unfortunately it's in portuguese, but maybe google translate helps you.
http://www.rcarvalhojs.com/dicas/de/backbone/2014/06/24/gerenciando-o-estado-da-aplicacao.html
I like to handle this, in this way
GetSomething:->
#result = #fetch(
success:()=>
#trigger "succesthing1" if #result .status is 204
#trigger "successThing2" if #result .status is 200
error:()=>
#trigger "errorThing" if #result .status is 401
)
Now i can listen for these trigger inside the view and take the correct action for a specific the result from server
There are currently I subscribe for of the Backbone sync, by sending events according to the promise that the request returned, see example below:
(function(Backbone) {
var methods, _sync;
_sync = Backbone.sync;
methods = {
beforeSend: function() {
return this.trigger("sync:start", this);
},
error: function() {
return this.trigger("sync:error", this);
},
complete: function() {
return this.trigger("sync:stop", this);
}
};
Backbone.sync = function(method, entity, options) {
var sync;
if (options == null) {
options = {};
}
_.defaults(options, {
beforeSend: _.bind(methods.beforeSend, entity),
error: _.bind(methods.error, entity)
complete: _.bind(methods.complete, entity)
});
sync = _sync(method, entity, options);
if (!entity._fetch && method === "read") {
return entity._fetch = sync;
}
};
})(Backbone);
Hope this helps.

Backbone/Marionette collection.create not firing callbacks

This might just be me not understanding Marionette's auto rendering, but I've been trying to add a model to my collection using .create and have been running into issues.
Calling .create hits the server, gets a successful response, and automatically hits my itemView.
What I need to do is call .create, get a successful response, and fire the callback in my create call.
My code currently looks like this:
collection.create(data, {
wait: true,
success: function(response) {
console.log(response);
},
error: function(error) {
console.log(error);
}
});
My success and error callbacks get totally ignored and the itemView is automatically initialized. Any thoughts?
I'm trying to reproduce but for me it works well. I'm using sinon.js fake server for this example. Hope my code could be helpful.
html:
<div id="app">
<div id="appRegion">nothing yet here</div>
</div>
js:
// fake API
var server = sinon.fakeServer.create();
server.respondWith("GET", "/api/models", [200, {
"Content-Type": "application/json"
},
JSON.stringify([{
'name': 'foo'
}, {
'name': 'bar'
}])]);
server.respondWith("POST", "/api/models", [200, {
"Content-Type": "application/json"
},
JSON.stringify({
'name': 'bazz'
})]);
// application
var Collection = Backbone.Collection.extend({
model: Backbone.Model,
url: "/api/models"
});
var MyApp = Marionette.Application.extend({
regions: {
appRegion: '#appRegion'
}
}),
MyView = Marionette.ItemView.extend({
className : 'myView',
template: _.template('<b><%=name%></b>')
}),
CollectionView = Marionette.CollectionView.extend({
childView: MyView
})
var collection = new Collection();
var myApp = new MyApp({
container: '#app'
});
var collectionView = new CollectionView({
collection: collection
});
myApp.appRegion.show(collectionView);
collection.fetch();
server.respond();
collection.create({}, {
wait: true,
success: function(model) {
console.log('success %o', model);
}
});
setTimeout(function(){
server.respond();
},2000)

Backbone.js model.save() sending multiple PUT requests

I have a backbone view that loads a model and some templates. When I submit the form in the edit template, backbone successfully sends a PUT request, just as it’s supposed to. On success, I navigate the user back to the view template.
However, if I navigate to the edit route again and submit the form, backbone sends two PUT requests. It then GETs the view template. If I navigate to the edit route a third time, backbone sends three PUT requests. The number of PUT requests keep incrementing every time I submit the form. Why might that be?
Here is my view:
// Filename views/users/edit.js
/*global define:false */
define([
'jquery',
'underscore',
'backbone',
'models/user/UserModel',
'text!templates/users/edit.html',
], function($, _, Backbone, UserModel, UserTemplate) {
var UserEdit = Backbone.View.extend({
el: '#page',
render: function (options) {
var that = this;
if (options.id) {
// modify existing user
var user = new UserModel({id: options.id});
user.fetch({
success: function (user) {
var template = _.template(UserTemplate, {user: user});
that.$el.animate({opacity: 0}, 180, function() {
that.$el.html(template).animate({opacity: 1}, 180);
});
}
});
} else {
// create new user
var template = _.template(UserTemplate, {user: null});
that.$el.animate({opacity: 0}, 180, function() {
that.$el.html(template).animate({opacity: 1}, 180);
});
}
},
events: {
'submit #create-user-form': 'createUser'
},
createUser: function (e) {
var postData = $(e.currentTarget).serializeObject();
var user = new UserModel();
user.save(postData, {
success: function (user, response) {
Backbone.history.navigate('#/users/view/' + response, {trigger: true, replace: true});
}
});
return false;
}
});
return UserEdit;
});
In my case, I could fix it by calling undelegateEvents() on the view in the success callback.
createUser: function (e) {
var postData = $(e.currentTarget).serializeObject(),
user = new UserModel(),
that = this;
user.save(postData, {
success: function (user, response) {
that.undelegateEvents();
Backbone.history.navigate('#/users/view/' + response, {trigger: true});
}
});
return false;
}
Thanks, #dbf.

Categories