From the backbone docs
getmodel.get(attribute)
Get the current value of an attribute from the model. For example: note.get("title")
I seeded some data with a name for each country into a Rails app
Country.create!(name: "Brazil")
Country.create!(name: "France")
Country.create!(name: "Germany")
Country.create!(name: "Spain")
In the console, I created a new collection and fetched the data
countries.fetch();
Object
XHR finished loading: "http://localhost:3000/countries".
Checked the length. Equal to the four countries I created.
countries.length
4
Selected a random one using underscore's shuffle method.
c = countries.shuffle()[0]
The object has a name
Backbone.Model
_changes: Array[2]
_currentAttributes: Object
_events: Object
_hasComputed: false
_previousAttributes: Object
attributes: Object
country: Object
created_at: "2013-01-07T06:09:43Z"
id: 2
name: "France"
updated_at: "2013-01-07T06:09:43Z"
__proto__: Object
__proto__: Object
Tried to get the name attribute from the object several different ways, all without success
c.get('name')
undefined
c.get("name");
undefined
c.get("name")
undefined
Can anyone think what I might be doing wrong?
One thing that I find unusual is that there is a 'country' attribute wrapping the other attributes
attributes: Object
country: Object
created_at: "2013-01-07T06:09:43Z"
id: 2
name: "France"
updated_at: "2013-01-07T06:09:43Z"
I'm not sure why 'country' is wrapping the other data. Is it because I created the seed data with a Country model?
Country.create!(name: "Brazil")
anyways, obj.get('country') doesn't return undefined
c = countries.shuffle()[0]
k = c.get('country')
Object
created_at: "2013-01-07T06:09:43Z"
id: 3
name: "Germany"
updated_at: "2013-01-07T06:09:43Z"
__proto__: Object
but I can't do a get on the name after that (i.e after I did the get on country)
k = c.get('country')
Object
k.get('name')
undefined
Is there a way to remove the country wrapper and just be able to do get on the attributes that it was created with?
Override model.parse to extract the country element. Backbone calls parse before populating the model from fetched data:
var Country = Backbone.Model.extend({
parse: function(attributes) {
return attributes.country;
}
});
Related
so I am passing an object from my App component to a child component.
Within the render method I am able to see the value of my object by using console.log as so
this.props.data.documents[0]
I am able to see the key value pairs of the object contained at documents[0],
but when I try to single out the individual properties (like below) I get an undefined error.
this.props.data.documents[0].username
This is what console.log(this.props.data.documents[0]) prints
{user_id: "5dfd9f8afc5bdf1bef11b78c", username: "christine", name: "second", src: "../images/5dfd9f8afc5bdf1bef11b78c_second.png"}
user_id: "5dfd9f8afc5bdf1bef11b78c"
username: "christine"
name: "second"
src: "../images/5dfd9f8afc5bdf1bef11b78c_second.png"
And here is the error for console.log(this.props.data.documents[0].src
react-dom.development.js:25206 Uncaught TypeError: Cannot read property 'src' of undefined
Why could this be? Thanks in advance.
I am learning Backbone.js. I have a model call myModel, and here is the console.log result when I call myModel.toJSON():
Object {accountId: "523f628e80d52a2805000004", added: "2013-09-26T06:26:12.765Z", updated: "2013-09-26T06:26:12.765Z", _id: "5243d384951b6cef05000004", name: Object}
I want to get the attributes in name, when I console.log myModel.toJSON().name, I got this result:
Object {first: "myfirst", last: "mylast"}
Everything works fine, until I call myModel.toJSON().name.first, I got a console error says
Cannot read property 'first' of undefined
I thought myModel.toJSON().name is an object, and to get the 'first' attribute from it, I just need to do myModel.toJSON().name.first. Any thought why it doesn't work?
This is the entire model I have:
r {cid: "c71", attributes: Object, collection: r, _changing: false, _previousAttributes: Object…}
_changing: false
_events: Object
_pending: false
_previousAttributes: Object
attributes: Object
_id: "5243d384951b6cef05000004"
accountId: "523f628e80d52a2805000004"
added: "2013-09-26T06:26:12.765Z"
name: Object
first: "myfirst"
last: "mylast"
__proto__: Object
updated: "2013-09-26T06:26:12.765Z"
__proto__: Object
changed: Object
cid: "c71"
collection: r
__proto__: s
Here is body of my model
urlRoot: '/users',
parse: function(response) {
return response.User;
}
Here is what is returned when I type /users/1 in my browser:
{"User":{"id":"1","created":"2013-02-13 09:22:42","modified":"2013-02-13 09:22:42","username":"somesuername","password":"","role":"somerole","token":null,"token_expiration":null}}
So the api works.
When I execute this:
this.model.id = 1;
this.model.fetch({ success: function(user){
console.log(user);
}}); // this.model is instance of my model
I get in console:
d {cid: "c4", attributes: Object, _changing: false, _previousAttributes: Object, changed: Object…}
_changing: false
_pending: false
_previousAttributes: Object
attributes: Object
__proto__: Object
changed: Object
cid: "c4"
id: Array[1]
__proto__: e
So the result was successful by model didn't fetch any data - am I missing something?
Backbone.Model stores the data inside the attributes property. From Backbone documentation:
The attributes property is the internal hash containing the model's state — usually (but not necessarily) a form of the JSON object representing the model data on the server. It's often a straightforward serialization of a row from the database, but it could also be client-side computed state.
Please use set to update the attributes instead of modifying them directly.
Try expanding the attributes node in the console object inspector, and you should see your data.
no amount of Googling is managing to solve my confusion so I thought I'd ask the question on here.
I'm trying to save a model and make use of success/error callbacks. On the backbone documentation it states you save your model like so: model.save([attributes], [options]).
I cannot find anywhere on the documentation that tells you how to save the entire model (i.e. without specifying the attributes), but have come across this question where the second answer says to save the entire model you can do model.save({}, [options]).
However I am trying this to no avail. My code is below:
Backbone Model:
class Student extends Backbone.Model
url: ->
'/students' + (if #isNew() then '' else '/' + #id)
validation:
first_name:
required: true
last_name:
required: true
email:
required: true
pattern: 'email'
schema: ->
first_name:
type: "Text"
title: "First Name"
last_name:
type: "Text"
title: "Last Name"
email:
type: "Text"
title: "Email"
In my view I have the following function:
class Students extends CPP.Views.Base
...
saveModel = ->
console.log "model before", #model.validate()
console.log "model attrs", #model.attributes
#model.save {},
wait: true
success: (model, response) ->
notify "success", "Updated Profile"
error: (model, response) =>
console.log "model after", #model.validate()
console.log "model after is valid", #model.isValid()
console.log "response", response
notify "error", "Couldn't Update"
In the first console.log before the save I am told that the model is valid, via the means of an undefined response. If indeed I look at the model I can see that all three fields are filled in.
Similarly in the next two console logs in the error #model.validate() and #model.isValid() both return undefined and true respectively.
However the response I get from trying to save the model is Object {first_name: "First name is required", last_name: "Last name is required", email: "Email is required"}
Finally in the console.log of the models attributes I get:
Object
created_at: "2012-12-29 23:14:54"
email: "email#email.com"
first_name: "John"
id: 2
last_name: "Doe"
type: "Student"
updated_at: "2012-12-30 09:25:01"
__proto__: Object
This leads me to believe that when I passed {} to my model it was actually trying to save the attributes as nil, else why else would it have errored?
Could someone kindly point out what I'm doing wrong? I'd rather not have to pass each attribute individually to the save!
Thanks in advance
From the suggested answer by Hui Zheng I modified my controller in my server to return the student in JSON format.
However to find the real source of the problem I read the backbone documentation on saving, and found out that when wait: true is given as an option it performs the following:
if (!done && options.wait) {
this.clear(silentOptions);
this.set(current, silentOptions);
}
On further investigation into clear I found
clear: function(options) {
var attrs = {};
for (var key in this.attributes) attrs[key] = void 0;
return this.set(attrs, _.extend({}, options, {unset: true}));
},
From this it looks as if every attribute is being cleared to then be reset. However on clearing my model the validations I wrote will fail (since first_name, last_name, email are required).
On the backbone.validation documentation we are told that we can use the parameter forceUpdate: true, so I have opted to use this when saving my model. I'm going to assume for now (although this might not be good practice) that the data from the server is correct since this has been validated too.
Therefore my final code is:
saveModel = ->
#model.save {},
wait: true
forceUpdate: true
success: (model, response) ->
notify "success", "Updated Profile"
error: (model, response) ->
notify "error", "Couldn't Update"
Are you sure that the model's attributes have been set correctly before save? Even none of its attributes has been set, it may still pass validate(depending on how validate function is defined). Please try to print the model in the console to verify that. BTW, it's better to pass null instead of {} in save, this way the model's set method won't be invoked.
Updated:
According to the Backbone's source code, if passing null as the first argument of save, the model's attributes will be kept intact until the model has been saved on the server successfully. So the other possibility is that your server has succeeded in saving the model but returned a corrupted object, resulting in failure in model's set method. If you still cannot fix the problem, tracing the model.set method might help。
By using Backbone-relational I would like to have the model task in this way:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: userModel
};
I did try this way (1) but the result is the following (2).
Any ideas?
(1)
var User = Backbone.RelationalModel.extend({
// urlRoot
});
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'user',
relatedModel: User
}
],
// urlRoot
});
(2)
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: null // null instead of having something related to user model
};
Not sure what your the exact JSON is for your Task model, so I'm guessing here.
Backbone-relational is expecting either a fully nested model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: {
name: 'Fred Rogers',
id: 42,
occupation: 'Hero'
}
};
Or a string/number, which it will assume to be the id of the related model:
task = {
id: 1
assigned_id: 2
name: 'read a book',
user: 42
};
I'm guessing you're hitting the second case, based on the null value you're getting for the user model.
When backbone-relational instantiates an instance of a model, and the related model is a "key" string/number, it will search its internal store of models to try to find a matching model. If it finds it, it sets that model as the value for the user property.
If it cannot find the model, it stashes the key in the model's relevant relation property model._relations[n].keyContents, and sets the user value to null.
It is at this point that you would use the fetchRelated function to get the related model from the datastore/API.
So, try calling task.fetchRelated() to get the related user model:
task.fetchRelated('user');