I am trying to filter some data from my collection. I am using where method for the job but it is returning an empty array. Here is the code.
Model:
return Backbone.Model.extend({
urlRoot: server_url + "tasks",
defaults: {
'id': null,
'title': '',
'description': '',
'deadline': null,
'priority': 1,
'status': 1,
'key': '',
'priority_name': '',
'status_name': ''
}
});
Collection:
return Backbone.Collection.extend({
url: server_url + "tasks",
model: TaskModel
});
And using it like:
var taskList = new TaskList();
taskList.fetch({
data: $.param({key: $.cookie('SID')}),
success: function(collection, response){
if(response.error){
window.location.replace('#logout');
}
}
});
taskList.where({status: 1});
taskList have all the data in it. It is not empty.
I have tried many combinations but hard luck every time.
I have also consulted from following posts but same result.
Backbone collection where clause with OR condition
Filter backbone collection by attribute value
toJSON on Backbone.Collection#where?
What I am missing here?
There doesn't appear to be anything wrong with the code you've posted, but then you're not showing us the population of your Collection. Remember that Backbone.Collection.where simply takes a literal and returns an array of matched Backbone.Model's. I have taken your code and simplified it to demonstrate a working example: http://jsfiddle.net/CK3Hz/
Edited as per comments below
Backbone.Collection.fetch's success callback receives (collection, response, options) arguments. If you are to perform the where on collection, this should work.
I have provided another jsfiddle to demonstrate using event propagation which I assume is your end goal.
Related
I did read a lot of the questions regarding this particular message, but they don't seem to apply in my case.
I have this model:
app.Template = Backbone.Model.extend({
defaults: {
name: '',
templateType: null,
content: '',
defaultOfType: false,
createdAt: null,
updatedAt: null
}
});
This collection:
var Templates = Backbone.Collection.extend({
model: app.Template,
url: '/templates'
});
app.Templates = new Templates();
In my router:
this.view = new app.TemplateFormView({ model: new app.Template() });
And in that view:
initialize: function() {
this.listenTo(app.Templates, 'add', this.editTemplate);
app.Templates.add(this.model);
// rendering function, other stuff
},
saveMyTemplate: function(e) {
e.preventDefault();
var formData = {};
var oldData = this.model.previousAttributes();
$(e.target).closest("form").find(":input").each(function() {
var el = $(this);
formData[el.attr("id")] = el.val();
});
this.model.set(formData).save();
}
When I try to save the model, I get this error:
Uncaught Error: A "url" property or function must be specified
As you can see, the url is set in the collection and the model is a part of the collection. Any idea as to why the model doesn't seem to be a member of the collection?
Thanks!
You might want to look into model.urlRoot parameter.
Specify a urlRoot if you're using a model outside of a collection, to enable the default url function to generate URLs based on the model id. "[urlRoot]/id"
Normally, you won't need to define this. Note that urlRoot may also be a function.
Also check if your references are correct to app and app.Templates.
I have requirement like backbone-js-model-different-url-for-create-and-update, but didn't get anything working out of it.
I have my Backbone Model as this:-
var task = backbone.Model.extend({
idAttribute: "TaskId",
defaults: {
TaskId: null,
Name: null,
TaskTypeId: null
},
// urlRoot: '/MyController/GetTasksAsync',
methodToURL: {
'read': '/MyController/Get',
'create': '/MyController/create',
'update': '/MyController/update',
'delete': '/MyController/remove'
},
sync: function (method, model, options) {
options = options || {};
options.url = model.methodToURL[method.toLowerCase()];
return Backbone.sync.apply(this, arguments);
}
});
Now, I am not getting how to call the Sync method?
This is what I tried but didn't work:-
this.model.sync("read",1,"");//(Get method, some hardcoded value /Get/1,no callback)
I similar lines how will I call the save method?
this.model.sync('update',model,'');
Am I missing anything??
I think what you're actually looking for are the Backbone Model methods fetch, save, and destroy which delegate to the sync method that you have overridden.
Here are the docs for fetch (save and destroy are nearby):
model.fetch
For example, to trigger the 'read' method you could call model.fetch().
I am using Backbone-Associations from
github-Backbone associations
https://github.com/dhruvaray/backbone-associations
for nested models to work with backnone.
I am getting an error while calling fetch() on a model. the response json from server exactly matches the model definitions. i cant figure out what i am missing...
Versions:
Backbone: 0.9.2
Backbone-associations: 0.2.0
TypeError: this.attributes[relationKey].off is not a function
this.attributes[relationKey].off("all");
//this is the code i am using..
var ProductVariation = Backbone.AssociatedModel.extend({
defaults: {
ImageUrl:'',
Desc:''
}
});
var Product = Backbone.AssociatedModel.extend({
relations: [{
type: Backbone.Many,
key: 'ProductVariations',
relatedModel: ProductVariation
}],
url: '/GetProductById',
defaults: {
CategoryId: 0,
ProductVariations: [],
Summary: ''
}
});
am i missing something? any help appreciated...
Oops it's my mistake...
Actually I was using an old version of BackboneJS, but thinking that I was using the latest..
Which doesn't have off and on methods on a collection, instead they use bind and unbind respectively.
Replacing the old one with new one is the fix.
I have a fetch request which response looks like this.
response = {
id: 1,
title: 'text',
followers: [{}, {}] // array of objects
}
As you can see the response is an object which have an attribute follower which is an array of object.
I would like to create from this response one model and one collection,
one which have the following attributes:
response = {
id: 1,
title: 'text'
}
and the other one, a collection of models
followers: [{}, {}];
What is the appropriate way to active my goal?
Could I use Backbone.Relation?
If yes, there are some example?
I'm used to use the same approach than #lecstor but I like more do it in the initialize() like this:
initialize: function(){
this.followers = new Followers( this.get("followers") );
}
depending on your needs/views/etc, I would probably wrap that response in a model and create a collection of models for followers...
MyModel = Backbone.Model.extend({
urlRoot: '/url/to/get/response'
});
Follower = Backbone.Model.extend();
Followers = Backbone.Collection.extend({
model: Follower
});
this.model = new MyModel({ id: 1 });
var that = this;
this.model.fetch({
success: function(model, response){
that.collection = new Followers( model.get('followers') )
}
});
I think you could then update your model from the collection quite easily with:
this.model.set('followers', this.collection.toJSON())
why not have a model that contains the collections and sub-models?
essentially a view-model
Solution
in my route
Myapp.Routes = Backbone.Router.extend({
init: function(){
user = new User();
user.fetch({user,
success: function(response){
user.classlist = new classes(response.attributes.classes);
});
}
});
I've got a serialized json array being returned from my server, and I am trying to put the nested objects into my nested collections.
This answer, I thought was going to get me there, but I'm missing something.
How to build a Collection/Model from nested JSON with Backbone.js
The json which I am trying to populate my nested model with is
{first_name: "Pete",age: 27, classes: [{class_name: "math", class_code: 42},{class_name: "french", class_code: 18}]}
I create my user model
MyApp.Models.Users = = Backbone.Model.extend({
initialize: function(){
this.classlist = new MyApp.Collections.ClassList();
this.classlist.parent = this;
}
});
I had tried to follow the example on the other page, and use
this.classlist = new MyApp.Collections.ClassList(this.get('classes'));
this.classlist.parent = this;
but this.get('classes') returns undefined.
I've also tried getting the classes array through this.attributes.classes, but that is also undefined.
------------updated to include re-initialize --------------------
The function where I am initializing the user and classes is in the User routes and is called re-initialize. I use this function to fetch the user and their classes and store the object.
re_initialize: function(id){
user = new MyApp.Models.User();
MyApp.editingClasses.url = 'classes/'+id;
MyApp.editingClasses.fetch({
success: function(response){
MyApp.editingClasses.parse(response);
}
});
new MyApp.Views.ClassesInput();
},
As you can see, I'm calling the parse explicitly in the success function, but it isn't adding the classes to the collection.
I can't include the 'collection' because for some reason I can't access it in backbone.
the user model, after getting returned to backbone includes the classes array, which I am trying to put into the ClassList collection.
The user model object copied from the javascript terminal looks like this.
attributes: Object
created_at: "2012-01-05T16:05:19Z"
id: 63
classes: Array[3]
0: Object
created_at: "2012-01-18T20:53:34Z"
id: 295
teacher_id: 63
class_code: 42
updated_at: "2012-01-18T20:53:34Z"
class_name: math
__proto__: Object
1: Object
2: Object
length: 3
__proto__: Array[0]
You can use the parse function to pre-process the server response:
MyApp.Models.Users = Backbone.Model.extend({
parse: function(response) {
var classesJSON = response.classes;
var classesCollection = MyApp.Collections.ClassList(classesJSON);
response.classes = classesCollection;
return response;
}
});
var user = new MyApp.Models.Users();
user.fetch();
// You should now be able to get the classlist with:
user.get('classes');
That said, the approach suggested in the other question should also work. It could be that when your initialize function is called, the model hasn't yet been populated with the data?
For example, if you're doing:
var user = new MyApp.Models.Users();
It won't have any attributes yet to give to the classlist collection. Could that be your problem?
Okay! you can maybe fetch the classes this way :
Model :
window.person = Backbone.Model.extend({
defaults: { }
});
Collection :
window.ClassesCollection = Backbone.Collection.extend({
model: person,
url: "http://your/url/data.json",
parse: function(response){
return response.classes;
}
});
Router :
window.AppRouter = Backbone.Router.extend({
routes: {
"" : "init"
},
init: function(){
this.classesColl = new ClassesCollection();
this.classesColl.fetch();
this.classesView = new ClassesView({collection: this.classesColl});
}
});
View : (for rendering every classes)
window.ClassesView = Backbone.View.extend({
el: $('...'),
template: _.template($("...").html()),
initialize: function() {
this.collection.bind("reset", this.render, this);
},
render: function(collection) {
_.each( collection.models, function(obj){
...
//obj.get('class_name') or obj.get('class_code')
...
}, this );
...
return this;
}
});