JavaScript: unable to access object properties - javascript

I'm having trouble accessing the properties of a simple object.
This is what I get when I run alert(JSON.stringify(user)):
{"username": "david", "biography": "Hello world."}
But this is what I get when I run alert(user.username):
undefined
I've also tried user["username"] with the same result. This is in the context of a Backbone application using Handlebars. Here is the Backbone part:
var User = Backbone.Model.extend({
urlRoot: 'http://api.example.com/user',
});
var Router = Backbone.Router.extend({
routes: {
":username": "profile"
},
profile: function (username) {
var user = new User({id: username});
user.fetch({
beforeSend: authenticate,
success: function() {
var profile = new Profile({user: user});
profile.render();
}
});
}
});
var Profile = Backbone.View.extend({
render: function() {
var source = $("#profile").html();
var template = Handlebars.compile(source);
user = this.options.user;
var html = template(user);
$("#content section").html(html);
}
});
What might be the cause such an issue?

if you user object is a backbone model, then try this
console.log(user.get('username'));
or
cosole.log(user.attributes.username);

This is working for me
var user = {"username": "david", "biography": "Hello world."};
alert (user.username);
alert (user["username"]);

JSON.stringify will look for a toJSON function and use the return value of that as the JSON it uses.
Backbone probably does some fancy coding to make it easier to use its model objects. Since they don't think you want all the junk they put in, they provided a clean toJSON() result for you.
#Rayweb_on has the rest of the answer.

Related

Backbone API fetch() from Model using API authentication

I have problem with my Backbone mobile app (using Cordova, Require, Handlebars, etc..).
In particular the console log of chrome give me this result:
.
I've tried different solutions taken by debugging and searching on the web.
The first are defining the urlRoot in my Model.backbone and calling the function mymodel.fetch(). And the result given is: .
This is the code:
var MyModel = Backbone.Model.extend({
constructorName: "MyModel",
urlRoot: 'http://192.168.56.101/XXX/api/categories/26?io_format=JSON'
});
myView: function() {
var model = new MyModel();
model.fetch();
// create the view
var page = new MyView({
model: model
});
// show the view
this.changePage(page);
},
The second solution is embedding the API KEY in the urlRoot. Like that:
var MyModel = Backbone.Model.extend({
constructorName: "MyModel",
urlRoot: 'http://IYI6M35MLB8UVW38fhj9RY3YPQWRX5X8H#192.168.56.101/XXX/api/categories/26?io_format=JSON'
});
The last solution that we tried was passing the header in the fetch call. Like this code:
myView: function() {
var model = new MyModel();
model.fetch({
headers: {
'Authorization': 'Basic IYI6M35MLB8UVW38Y99RrgsrPQWRX5X8H:'
}
});
// create the view
var page = new MyView({
model: model
});
// show the view
this.changePage(page);
},
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
All of this solutions give me the same result, like "Chrome Console LOG", he sad me "Unauthorized etc.." like the image.
Can you give me some help? How can I bring JSON object in a model in Backbone using API with authentication by Username?

Titanium, Alloy use instance of a model in two windows

I am using Alloy Titanium and I wanted to do something like this :
I have a model, view and controller, this is the view index.xml -
<Alloy>
<Model src="post" instance="true" id="postIns"/>
<Window class="container" onSwipe="update" model="$.postIns">
<Label id="postTitle" top="15">{$.postIns.title}</Label>
<Label id="postContent">{$.postIns.body}</Label>
<Button id="updateButton" onClick="update" bottom="0">Zemi nov post</Button>
</Window>
this is the model - post.js -
exports.definition = {
config: {
"defaults": {
"userId": "",
"id": "",
"title": "Title",
"body": "",
},
adapter: {
type: "properties",
collection_name: "post"
}
},
extendModel: function(Model) {
_.extend(Model.prototype, {
// extended functions and properties go here
});
return Model;
},
extendCollection: function(Collection) {
_.extend(Collection.prototype, {
// extended functions and properties go here
});
return Collection;
}
};
and my controller index.js that connects to a fake api and fills the instance of the model -
var id = 1;
function update() {
id =_.random(0, 50);
var results = {};
var client = Ti.Network.createHTTPClient({
// called when the response data is available
onload : function(e) {
results = JSON.parse(client.responseText);
// display results on console
Ti.API.info(JSON.stringify(results,null,2));
// save the results to the instance
$.postIns.save(results);
},
// called when an error occurs, including a timeout
onerror : function(e) {
results = JSON.parse(client.responseText);
// display error results on the console
//Ti.API.err(JSON.stringify(results,null,2));
},
});
var url = "http://jsonplaceholder.typicode.com/posts/" + id;
client.open("GET", url);
client.send();
}
$.index.open();
Now let's say I wanted to make another view file .xml with a different window, how would I go about using the same instance of the post model in that window?
P.S. I am pretty sure that the model instance I made is local, but I am interested in a solution about binding a model to more windows.
You can check the titanium docs which clearly explains about the global singleton instance of the model and I think you will be able to use it through out.
Check out the Titanium doc words :
You can also create a global singleton instance of a model, either in markup or in the controller, which may be accessed in all controllers. Use the Alloy.Models.instance method with the name of the model file minus the extension as the only parameter to create or access the singleton.
// This will create a singleton if it has not been previously created,
// or retrieves the singleton if it already exists.
var book = Alloy.Models.instance('book');
Hope it gives some idea.

Backbone Collection Fetch and the form of the Request

I have a backbone collection
var Stuff = Backbone.Collection.extend({
url: "stuff/"
model: StuffModel
});
I also have an array of ids:
var ids = [ 1, 2, 3, 4 ];
As per the docs, I call fetch on Stuff like so:
this.collection.fetch( { $.param({ ids : exercise_ids.join( "," )})});
This sends a request to the server of the form:
/stuff/?ids=1,2,3,4
This works, but I'm not happy with the form of the request. Is there a way I can send the request with the following form (ie not use the querystring)
/stuff/1,2,3,4
Thanks (in advance) for your help.
Assuming the backend sees [param] as ids when you do /stuff/[param] then there is no difference in functionality. These request are made behind the scenes and don't affect the browser's address bar so there isn't really any concern here. If you want to format your url you can define url as a function in your Backbone Collection
var Stuff = Backbone.Collection.extend({
initialize: function(models, options) {
this.ids = options.ids
//bind functions to 'this' so that you can access ids
_.bind(this, 'setIds', 'url');
},
setIds: function(ids) {
this.ids = ids;
//return 'this' to allow chaining
return this;
},
url: function() {
return 'stuff/' + this.ids.join(',')
}
});
myCollection.setIds([1,2,3,4]).fetch()

Problems with fetching and parsing using Backbone.js

I try to fetch this server: http://cshosting.webfactional.com/api/v1/projects/?format=json
to a backbone.js collection.
Then I try to console.log it, but it's not working.
It is very important to me, please help.
NEWS: I figured out it's something with JSONP. will be glad to hear more information about that. thanks.
this is parts of my code in short:
window.ProjectList = Backbone.Collection.extend({
model: Project,
url:"http://cshosting.webfactional.com/api/v1/projects",
parse: function(response) {
return response.objects;
}
});
another part:
window.HomeView = Backbone.View.extend({
initialize:function () {
this.projectList = new ProjectList();
this.projectList.fetch({success : function() {console.log(this.projectList); }});
this.homeListView = new HomeListView({model: this.projectList});
}
});
The this on the fetch callback is not going to refer to your HomeView instance. Try using another variable to ensure you are referencing the desired object.
initialize:function () {
var self = this;
this.projectList = new ProjectList();
this.projectList.fetch({success : function() {console.log(self.projectList); }});
this.homeListView = new HomeListView({model: this.projectList});
}
If that doesn't solve the problem, please describe what happens. Use the webkit inspector's network tab to make sure the correct GET request and response are being called. Make sure your parse function is being called and the response object is what you expect.
It seems like you would want to do something more like this:
window.Project = Backbone.Model.extend({
url:"http://cshosting.webfactional.com/api/v1/projects/?format=json"
});
window.ProjectList = Backbone.Collection.extend({
model: Project,
url:"http://cshosting.webfactional.com/api/v1/projects/?format=json"
});
window.HomeView = Backbone.View.extend({
initialize:function () {
_.bindAll(this, 'render');
},
render: function(){
var self = this;
console.log(self.collection);
return this;
}
});
var project = new Project();
var collection = new ProjectList();
collection.fetch({
success: function(result_collection, resp) {
var view = new HomeView ({ collection: result_collection });
view.render();
}
});

How do I fetch a single model in Backbone?

I have a Clock model in Backbone:
var Clock = Backbone.Model.extend({});
I'm trying to get an instance of that that has the latest information from /clocks/123. Some things I've tried:
a "class"-level method
Clock.fetch(123)
// TypeError: Object function (){ ... } has no method 'fetch'
creating an instance and then calling fetch on it:
c = new Clock({id: 123})
c.fetch()
// Error: A 'url' property or function must be specified
a collection
I tried creating an AllClocks collection resource (even though I have no use for such a thing on the page):
var AllClocks = Backbone.Collection.extend({
model: Clock,
url: '/clocks/'
});
var allClocks = new AllClocks();
allClocks.fetch(123);
// returns everything from /clocks/
How do I just get one API-backed Clock?
Try specifying urlRoot in the model:
From the docs:
var Book = Backbone.Model.extend({urlRoot : '/books'});
var solaris = new Book({id: "1083-lem-solaris"});
solaris.fetch();
Your second approach is the approach I have used. Try adding the following to your Clock model:
url : function() {
var base = 'clocks';
if (this.isNew()) return base;
return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + this.id;
},
This approach assumes that you have implemented controllers with the hashbang in your URL like so, http://www.mydomain.com/#clocks/123 , but it should work even if you haven't yet.
I personally recommend, following the Model#url method documentation
model = new Model(id: 1)
view = new View(model: model)
collection = new Collection([model])
model.fetch()
in your collection remember to add the collection url:
url: "/models"
and in your View's initialize function do:
this.model.bind("change", this.render)
this way backbone will do an ajax request using this url:
"/models/1"
your model will be updated and the view rendered, without modifying Collection#url or Model#urlRoot
note:
sorry this example came out in coffee script, but you can easily translate it to js adding var statements
var Person = Backbone.Model.extend({urlRoot : '/person/details'});
var myName = new Person({id: "12345"});
myName.fetch();
As a result you make a Ajax request on the
URL http://[domainName]/person/details/id
and you have the JSON response back.
Enjoiiii !!!
...and do this if you don't want the trailing slash on the model urlRoot:
url : function() {
return this.urlRoot + this.id;
},
You probably should be accessing the object trough a collection and keeping it in the collection all the time. This is how to do it:
var AllClocks = Backbone.Collection.extend({
model: Clock,
url: '/clocks/'
});
var allClocks = new AllClocks();
my_clock = allClocks.add({id: 123});
my_clock.fetch()
I want to use RESTful url,but I couldn't understand why 'postId' can't be added to base url.
var PostModel = Backbone.Model.extend({
urlRoot: 'getBlogPost',
defaults: {
postTitle: "defaultTitle",
postTime: "1970-01-01",
postContent: "defaultContent",
postAuthor: "anonymous"
}
});
var post = new PostModel({
postId: 1
});
alert(post.url());
Then I know only after I set 'idAttribute' as 'postId' in Model can I get the right url.
like this:
var PostModel = Backbone.Model.extend({
idAttribute: 'postId',
urlRoot: 'getBlogPost',
defaults: {
postTitle: "defaultTitle",
postTime: "1970-01-01",
postContent: "defaultContent",
postAuthor: "anonymous"
}
});

Categories

Resources