Backbone.syphon infinite loop? - backbone.js

I'm trying to use Backbone.syphon like so:
var WhoChoiceView = Marionette.ItemView.extend({
template: template,
model: Model,
events:{
'click #start_add_person': 'addPerson'
},
addPerson: function(){
var data = Syphon.serialize(this);
this.model.set(data);
this.model.save();
}
});
The use of syphon should be limited to the button click event, but I get this error when I'm showing views:
`Uncaught RangeError: Maximum call stack size exceeded
(anonymous function)
forEach
Backbone.Syphon.flattenData
Backbone.Syphon.flattenData
(anonymous function)
forEach ...`
There were no line numbers on this part of the stacktrace. The last two line of my code were:
console.log('app:show:content');
App.content.show(view); // I'm using marionette(App) and ItemView
I'm not sure how the flattenData method is called. Has anyone seen this behavior?
I'm using Backbone.Syphon, v0.4.1
Thanks,
Andrew

Related

Backbone collection.fetch() causing TypeError: this.model is undefined

everything seems correct, but whenever I do the following, I get TypeError: f is undefined in backbone 1.1.2, Also, when I debug, I saw that it was able to receive the correct response, yet when I do categories.toJSON() I get nothing:
var categories = new App.Lookup.CategoryCollection();
categories.url = 'index.php?r=lookupapi/categories';
categories.fetch();
App.Lookup.CategoryCollection = Backbone.Collection.extend({
model: App.Lookup.CategoryModel
});
App.Lookup.CategoryModel = Backbone.Model.extend({
});
What am I doing wrong here?
Update:
I use the development version as suggested by user972 and got the following error message:
TypeError: this.model is undefined
categories.fetch() is the one causing the error, it pointed to this function in backbone:
// Define how to uniquely identify models in the collection.
modelId: function (attrs) {
return attrs[this.model.prototype.idAttribute || 'id'];
},
But I still couldn't figure out why it is undefined.
The declaration of App.Lookup.CategoryModel is not hoisted above App.Lookup.CategoryCollection. You need to define App.Lookup.CategoryModel before you use it.
So change your code to:
App.Lookup.CategoryModel = Backbone.Model.extend();
App.Lookup.CategoryCollection = Backbone.Collection.extend({
model: App.Lookup.CategoryModel
});
var categories = new App.Lookup.CategoryCollection();
categories.url = 'index.php?r=lookupapi/categories';
categories.fetch();
In response to:
I saw that it was able to receive the correct response, yet when I do
categories.toJSON() I get nothing
If you want to see the results of fetch you need to pass a success callback:
categories.fetch({
success: function(collection, response, options) {
console.log(collection.toJSON());
}
});
Just out of curiosity, have you referenced the script files in the proper order? It seems more of from script loading error than the code based.
<script src="underscore-1.6.0-min.js"></script>
<script src="backbone-1.1.2-min.js"></script>
Other thing that might be of help is to use non-min version of backbone and try locating where it is crashing and why?
<script src="http://backbonejs.org/backbone.js"></script>

Backbone.js - each method throw error, while loop the models

In my view - after I fetch the data from collection, I am trying to loop the models using "native" - each method, but I am getting an error:
Uncaught TypeError: Object [object Object] has no method 'each'
still I am able to convert my models to json objects..
console.log(models.toJSON()); // giving result
models.each(function(model){
console.log(model); // throw the error.. why..?
})
Here is the part of the view where I am consoling:
initialize:function(){
var that = this;
this.collection = headerCollection;
this.listenTo(this.collection, "add", this.addAll);
this.collection.fetch();
},
addAll:function(models){
models.each(function(model){
console.log(model);
})
console.log(models.toJSON());
},
What would be the issue?
If you look at the Catalog of events in docs, it says that arguments being passed to collection's add event handler are (model, collection, options), so model won't have each method with it. May be you can listen to reset event as the arguments being passed for that are (collection, options).
Then you should be able to do models.each in addAll method.
It does not look like the collection is passed to your addAll method as an actual collection but as an array?
What does console.log(typeof models) do?
If you bind the eventhandler to this you can access the collection that way.
initialize:function(){
var that = this;
this.collection = headerCollection;
this.collection.on("add", this.addAll, this);
this.collection.fetch();
},
addAll:function() {
this.collection.each(function(model){
console.log(model);
})
console.log(this.collection.toJSON());
},
I am not familiar with the listenTo method so I don't know what that does.

Object #<HTMLTableSectionElement> has no method 'append' in Backbone.js View self.el

Window.TableView = Backbone.View.extend({
initialize: function() {
},
tagName:"tbody",
render: function() {
var self=this;
console.log(self.el);//will log <tbody></tbody>self.el.append("<tr></tr>");
return self.el;
}
);
tbView=new TableView();
tbView.render();
If I build a new view, and call the render function; I'll get the error Uncaught TypeError: Object # has no method 'append' has no method 'append' ...Is there a way to get it work?
Thanks!
Backbone view.el is a reference to the raw DOM object, which has no method append. In order to manipulate the element using jQuery, you should use the cached jQuery selector property view.$el instead:
self.$el.append("<tr></tr>");

Rendering Handlebars template with Backbone

I have a Backbone view (see below) that I believe to be doing the right thing
Index = Backbone.View.extend({
render: function() {
var activities = new Activities();
activities.fetch();
var tpl = Handlebars.compile($("#activities-template").html());
$(this.el).html(tpl({activities: activities.toJSON()}));
return this;
}
});
If execute each line in the render() function with Chrome JS console I get the expected result with the element I pass in getting populated with the template output. However, when I run this using the following
var i = new Index({el: $("body")})
i.render()
"i.$el" is completely empty--the HTML is not getting rendered like it does in console. Any ideas why?
fetch is an AJAX call so there's no guarantee that activities.toJSON() will give you any data when you do this:
activities.fetch();
var tpl = Handlebars.compile($("#activities-template").html());
$(this.el).html(tpl({activities: activities.toJSON()}));
Executing the code in the console probably gives the AJAX call time to return with something before you try to use activities.
You should do two things:
Fix your template to do something sensible (such as show a loading... message of some sort) if activities is empty.
Attach your view's render to the collection's "reset" event:
initialize: function() {
// Or, more commonly, create the collection outside the view
// and say `new View({ collection: ... })`
this.collection = new Activities();
this.collection.on('reset', this.render, this);
this.collection.fetch();
},
render: function() {
var tpl = Handlebars.compile($("#activities-template").html());
this.$el.html(tpl({activities: this.collection.toJSON()}));
return this;
}
I also switched to this.$el, there's no need to $(this.el) when Backbone already gives you this.$el.

Backbone.js: retrieving a collection from the server in PHP

I'm having a look at Backbone.js, but I'm stuck. The code until now is as simple as is possible, but I seem not to get it. I use Firebug and this.moments in the render of MomentsView is an object, but all the methods from a collection don't work (ie this.moments.get(1) doesn't work).
The code:
var Moment = Backbone.Model.extend({
});
var Moments = Backbone.Collection.extend({
model: Moment,
url: 'moments',
initialize: function() {
this.fetch();
}
});
var MomentsView = Backbone.View.extend({
el: $('body'),
initialize: function() {
_.bindAll(this, 'render');
this.moments = new Moments();
},
render: function() {
_.each(this.moments, function(moment) {
console.log(moment.get('id'));
});
return this;
}
})
var momentsview = new MomentsView();
momentsview.render();
The (dummy) response from te server:
[{"id":"1","title":"this is the moment","description":"another descr","day":"12"},{"id":"2","title":"this is the mament","description":"onother dascr","day":"14"}]
The object has two models according to the DOM in Firebug, but the methods do not work. Does anybode have an idea how to get the collection to work in the view?
The problem here is that you're fetching the data asynchronously when you initialize the MomentsView view, but you're calling momentsview.render() synchronously, right away. The data you're expecting hasn't come back from the server yet, so you'll run into problems. I believe this will work if you call render in a callback to be executed once fetch() is complete.
Also, I don't think you can call _.each(this.moments) - to iterate over a collection, use this.moments.each().
Try removing the '()' when instantiate the collection.
this.moments = new Moments;
Also, as it's an asynchronous call, bind the collection's 'change' event with the rendering.
I hope it helps you.

Resources