I have a problem trying to display collection items, in particular I get an error on collection.each() function:
getTodo: function(){
this.todos = new TodosCollection;
this.todos.query = new Parse.Query("test");
this.todos.fetch({
success:function(obj){
console.log(obj.length);
obj.each(this.addOne);
}
});
},
addOne: function(todo){
console.log(todo);
}
with this code I get this error:
Uncaught TypeError: undefined is not a function
console.log(obj.lenght) is != 0, so where is the error?
The this from which you call the addOne method is the callback, not your object - and the callback's property addOne is undefined, so you're trying to call undefined as a function. You can bind the callback to the object scope this way:
success: _.bind(function(obj){
obj.each(this.addOne);
}, this)
Related
I'm updating the 'backgroundColor' property of the all the objects nested within a sliderSegmentStyleDict state object using the following:
setSliderSegmentStyleDict(prevState => {
let updatedSegmentStyleDict = prevState
for(let segmentIndex in Object.keys(updatedSegmentStyleDict)) {
segmentIndex = Object.keys(updatedSegmentStyleDict)[segmentIndex]
let segmentDict = updatedSegmentStyleDict[segmentIndex]
segmentDict['backgroundColor'] = snappedSegmentIndex > segmentIndex ? '#19486A' : '#d1d5db'
updatedSegmentStyleDict[segmentIndex] = segmentDict
}
return updatedSegmentStyleDict
})
The first time the component renders, it works fine and sets the appropriate colour.
However, when I subsequently invoke this function manually, I get the following error in the console:
Uncaught TypeError: Cannot assign to read only property 'backgroundColor' of object '#<Object>'
Why am I unable to modify the backgroundColor property of segmentDict object?
I have this code that gets some data from a MongoDB and saves it in an array in my component.
this.laugService.getAllLaug().subscribe(laug => {
this.laugs = laug; //save posts in array
});
this.laugs.array.forEach(element => {
this.modelLaugs.push(new Laug(element.navn, element.beskrivelse))
});
After that i want to save this data to a different array, where i create new instances of my model "Laug". For this i am using a foreach loop, however i am getting an error when running this code:
ERROR Error: Uncaught (in promise): TypeError: Cannot read property
'forEach' of undefined
TypeError: Cannot read property 'forEach' of undefined
I am certain that i receive the data from the DB, however i am unsure why my array is undefined at this point.
Your subscription is asynchronous. The laugs property may not be set when you are trying to iterate. Just put the forEach code inside the subscribe callback:
this.laugService.getAllLaug().subscribe(laug => {
this.laugs = laug; //save posts in array
if (this.laugs && this.laugs.array) {
this.laugs.array.forEach(element => {
this.modelLaugs.push(new Laug(element.navn, element.beskrivelse))
});
}
});
My Code:
I am new to Backbone.js and trying to build an app with Backbone.js and PHP. When I am trying to call add in the router, I am getting error:
Uncaught TypeError: Object [object Object] has no method 'set'.
Please help me to find my mistake.
Thanks.
// Models
window.Users = Backbone.Model.extend({
urlRoot:"./bb-api/users",
defaults:{
"id":null,
"name":"",
"email":"",
"designation":""
}
});
window.UsersCollection = Backbone.Collection.extend({
model:Users,
url:"./bb-api/users"
});
// Views
window.AddUserView = Backbone.View.extend({
template:_.template($('#new-user-tpl').html()),
initialize:function(){
this.model.bind("click", this.render, this);
},
render:function(){
$(this.el).html(this.template(this.model.toJSON()));
return this;
},
events:{
"click .add":"saveUser"
},
saveUser:function(){ alert('saveUser');
this.model.set({
name:$("#name").val(),
email:$("#email").val(),
designation:$("#designation").val()
});
if(this.model.isNew()){
this.model.create(this.model);
}
return false;
}
});
// Router
var AppRouter = Backbone.Router.extend({
routes:{
"":"welcome",
"users":"list",
"users/:id":"userDetails",
"add":"addUser"
},
addUser:function(){
this.addUserModel = new UsersCollection();
this.addUserView = new AddUserView({model:this.addUserModel});
$('#content').html(this.addUserView.render().el);
}
});
var app = new AppRouter();
Backbone.history.start();
As suggested in the comments, the problem starts here here:
this.addUserModel = new UsersCollection();
this.addUserView = new AddUserView({model:this.addUserModel});
and finishes here:
saveUser:function(){ alert('saveUser');
this.model.set({
By passing a collection in place of a model you create confusion, and as a result later in the saveUser function you try to call a Backbone.Model method (set) on a Backbone.Collection instance.
Note: As of version 1.0.0 Backbone.Collection now has a set method. In previous versions, such as the one used by the question's author, that method was instead called update.
There are several steps you can take to clarify this code. For starters, I would rename your model and collection classes so that it's clear that the model is the singular form and the collection is the plural form:
window.Users => window.User
window.UsersCollection => window.Users
Next, I would create a new User model, instead of a Users collection, and pass that to your view:
this.addUserModel = new User();
this.addUserView = new AddUserView({model:this.addUserModel});
Finally, I'd remove these lines:
if(this.model.isNew()){
this.model.create(this.model);
}
For one thing, the model will always be new (as you just created it before passing it in), but more importantly you don't need to call the Collection's create method because that method creates a new model, when you already have one created. Perhaps what you should add instead is :
this.model.save();
if your intent is to save the model to your server.
Since you already specified a urlRoot for the model, that should be all you need to create a new model, pass it to your view, have your view fill in its attributes based on DOM elements, and finally save that model's attributes to your server.
I think you are facing problem with object scope. When event fired it send to event object to that function. Just try this it may work
Declare global variable with the current view inside the initialize
initialize : function(){ self = this; }
then change this to self,
saveUser:function(){ alert('saveUser');
self.model.set({
name:$("#name").val(),
email:$("#email").val(),
designation:$("#designation").val()
});
if(self.model.isNew()){
self.model.create(this.model);
}
return false;
}
I have two models (User and Task) which are instances of Backbone.RelationalModel.
The relation about these two models is the following:
// Task model
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: 'HasOne',
key: 'user',
relatedModel: User
}
],
urlRoot: 'someUrl'
});
Then I have one collection which code looks like this:
var FollowerCollection = Backbone.Collection.extend({
initialize: function () {
_.bindAll(this);
}
model: User
});
var User = Backbone.RelationalModel.extend({
});
When I make a fetch on FollowerCollection I get the following error:
Uncaught TypeError: Cannot read property 'idAttribute' of undefined
on the line 1565 of backbone-relation.js of backbone-relation version 0.5.0
Here a piece of code of backbone-relation.js
if ( !( model instanceof Backbone.Model ) ) {
// Try to find 'model' in Backbone.store. If it already exists, set the new properties on it.
var existingModel = Backbone.Relational.store.find( this.model, model[ this.model.prototype.idAttribute ] );
The problem is related to _.bindAll(this) because if I comment it, it works properly.
Why? Any ideas?
Removing the _.bindAll does work.
It's a shame, because it's a really handy function. It must interact with some part of Backbone badly. I'm on v9.10
I use this method all the time, and issues only come up sometimes (like when you want to do a bulk add to a collection).
For me, The problem was in this Backbone.js method:
// Get a model from the set by id.
get: function(obj) {
if (obj == null) return void 0;
this._idAttr || (this._idAttr = this.model.prototype.idAttribute);
return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];
},
The code fails at this.model.prototype because prototype is undefined. What? Ya. For reals.
The problem is that when _.bindAll is called, it binds all properties of the collection, as #jakee says. This seems to include Collection.model, which is a bug I think.
The solution is to bind individual methods until this is fixed.
There's an existing, but closed issue on github: https://github.com/documentcloud/backbone/issues/2080
Seems like the current maintainers don't like the method, but I don't understand why.
Like my project is really big I had to create my custom bindAll. Here you have the code, it works with the lastest versions.
I bind all the properties of the instance "this" except the ones that has prototype with properties, like this.model in a Collection
https://gist.github.com/patrixd/8025952
//bindAll from underscore that allows 1 argument to bind all the functions from the prototype,
//or if there are more arguments they will be the only binded
_.originalBindAll = _.bindAll;
_.bindAll = function (that) {
var funcs = Array.prototype.slice.call(arguments, 1),
validKeys = [], fn;
if (funcs.length == 0) {
for (var i in that) {
fn = that[i];
if (fn && typeof fn == "function" && (!fn.prototype ||
_.keys(fn.prototype).length == 0))
validKeys.push(i);
}
_.originalBindAll.apply(_, [that].concat(validKeys));
}
else
_.originalBindAll.apply(_, arguments);
};
I have a recipe model, and a recipe has an ingredientlist collection which stores a bunch of ingredients.
When I add an ingredient to the ingredient list from a form submit, I have to get an 'id' from the server, so I do an ajax request, get the id, and am trying to then add the ingredient to the model.
In my ingredientlist.view, I have
initialize: function(){
this.recipe = this.model;
},
get_ingredient: function(ingredient){
var ingredient_id = new MyApp.Models.Ingredient;
ingredient.url='/ingredients/?ing='+encodeURIComponent(ingredient_array[i]);
ingredient.fetch({
success: function() {
this.recipe('add:ingredients', function(ingredient,ingredientlist){
});
},
error: function() {
new Error({ message: "adding ingredient" });
}
});
}
I didn't include the function which triggers the 'get_ingredient', because it I am getting the ajax fine, so the problem isn't in triggering the 'get_ingredient'.
I get the errorUncaught TypeError: Property 'recipe' of object [object DOMWindow] is not a function
using the existing code.
what is the best way to accomplish something like this?
First of All i'm a newbie too with backbone.js!
So my thoughts is :
U need to bind your get_ingredient in your View : look bind to trigger your functions!
Try to pass the Context (this) to "get_ingredients"
This is just my 5 cents