im have the next Model and Collection definition:
var Auditoria = Backbone.Model.extend({
defaults:{
id: 'undefined',
user_id: 'undefined',
user_str: 'undefined',
user_agent: 'undefined',
login_from: 'undefined',
login_date: 'undefined'
}
});
var AuditoriaList = Backbone.Collection.extend({
model: Auditoria,
url: $("#ajax-call").val()
});
var sesiones = new AuditoriaList();
sesiones.fetch({
async: false
});
The collection is created correctly, a logging says:
{length: 15, models: Array[15], _byId: Object, constructor: function,
model: function…}
But when try iterate the collection (inside a render view method), apparently, not get correctly the current element:
render: function(){
sesiones.each(function(sesion){
console.log(sesion);
}, this);
return this;
}
The console.log, not return models, return:
{cid: "c1", attributes: Object, collection: r, _changing: false,
_previousAttributes: Object…}
Any ideas ?.
If you want to get your model's value, you should iterate collection like this:
sesiones.forEach(function(model) {
console.log(model.get('user_str'));
}
{cid: "c1", attributes: Object, collection: r, _changing: false, _previousAttributes: Object…}
This is model from your collection
I guess what you are expecting to see in your console log is the JSON representation of your model data? Try this:
console.log( sesion.toJSON() );
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 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.
I have been trying to display some data(a json object with only three properties) by fetching it from server (2 lines of php code). To fetch and display that data in html page I've used BackboneJS and Handlebars template respectively. Here is the javascript code
var User = Backbone.Model.extend({
urlRoot:"getUser/"
});
var UserView = Backbone.View.extend({
el:$("#user"),
initialize: function(){
this.model.bind("change", this.render());
},
render: function(){
var templateSource = $("#user-temp").html();
var template = Handlebars.compile(templateSource);
$(this.el).html(template(this.model));
var newDate = new Date();
console.log("in UserView render :: " + newDate.getTime());
console.log(this.model.toJSON());
//var pp = "nothing";
}
});
var UserRouter = Backbone.Router.extend({
routes:{
"":"userDetails"
},
userDetails:function(){
//var newUser = new User({id:1});
var newUser = new User();
var userView = new UserView({model:newUser});
var newDate = new Date();
newUser.fetch({
success:function(){
console.log("in router :: " + newDate.getTime());
console.log(userView.model.toJSON());
}
});
}
});
Handlebars template in index.html page
<div id="user"></div>
<script id="user-temp" type="text/x-handlebars-template">
<div>
ID {{attributes.id}}
Name {{attributes.name}}
Age {{attributes.age}}
</div>
</script>
PHP code
$user = array("name"=>"Arif","id"=>"1","age"=>"100");
echo json_encode($user);
Now the problem is I can't see the data ($user) i'm sending from server in index.html page, in console (google chrome) i've rather found this
in UserView render() :: 1350880026092
Object
__proto__: Object
in router :: 1350880026097
Object
age: "100"
id: "1"
name: "Arif"
__proto__: Object
(The BIG numbers in console is time in milliseconds.)
But If I change the code for console output (just showing the model)
(in UserView render() function)
console.log(this.model);
(in UserRouter userDetails() function)
console.log(userView.model);
Then the console looks like this
in UserView render :: 1350881027988
child
_changing: false
_escapedAttributes: Object
_pending: Object
_previousAttributes: Object
_silent: Object
attributes: Object <<======
age: "100"
id: "1"
name: "Arif"
__proto__: Object
changed: Object
cid: "c0"
id: "1"
__proto__: ctor
in router :: 1350881027995
child
_changing: false
_escapedAttributes: Object
_pending: Object
_previousAttributes: Object
_silent: Object
attributes: Object <<======
age: "100"
id: "1"
name: "Arif"
__proto__: Object
changed: Object
cid: "c0"
id: "1"
__proto__: ctor
Here i can see the attributes (arrow marks <<====== )
So what am i doing wrong? Am i missing some basic concepts here? By the way, I'm new to Handlebars and BackboneJS. Moreover its my first question in stackoverflow, so if you think the info i've given isn't enough, please feel free to ask what further info you need.
Thanks in advance.
You bind your model to this.render() which you means you execute your render function and then bind your model to whatever render returns (nothing, in your case).
Try
initialize: function(){
_.bindAll(this, 'render'); // guarantees the context for render
this.model.bind("change", this.render);
}
or, with a more up to date syntax (see the changelog for 0.9.0 http://backbonejs.org/#changelog, bind and unbind have been renamed to on and off for clarity)
initialize: function(){
_.bindAll(this, 'render');
this.model.on("change", this.render);
}
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;
}
});