Backbone collection.add is not working - javascript

I have a pretty basic setup like this:
var MusicModel = Backbone.Model.extend({});
var PlaylistCollection = Backbone.Collection.extend({
model: MusicModel,
events: {'add':'add'},
add: function(mdl){
//This is working perfectly fine even output of model
console.log(mdl);
}
});
var playlistCollection = new PlaylistCollection();
playlistCollection.add(new Music(data));
The model is not actually added to the collection. If I try to use Chrome console and enter playlistCollection.length it will output 0 and playlistCollection.models will output [].
Any idea what I am doing wrong?

Collections in Backbone already have an add method. By writing your own, you mask the base method and prevent the the normal behavior: inserting a model into the collection. Rename your method to something else or call the base method to solve your problem:
var PlaylistCollection = Backbone.Collection.extend({
model: MusicModel,
add: function(model, opts){
Backbone.Collection.prototype.add.call(this, model, opts);
console.log(model);
}
});
http://jsfiddle.net/nikoshr/WPrTu/

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?

Proper way of populating Backbone Collection

I have the following Backbone Model and Collection
/**
* DataPoint
*/
var DataPoint = Backbone.Model.extend({
defaults: {
ts: null,
value: null
}
});
var DataPointCollection = Backbone.Collection.extend({
model: DataPoint
});
In order to populate and do what I need to do with the data I do something similar to this:
url = '/api/v1/database/1/data';
$.getJSON(url, params, function(data) {
var dps = new DataPointCollection;
dps.add(data.datapoints);
//Now do stuff with dps
});
I'm sure there is a better way to do this with Backbone but not sure how. I feel it should be more like telling the DataPoint collection to populate itself.
How to approach this on backbone?
Have a look at the docs, fetch is what you're looking for; here's the example took from there:
var accounts = new Backbone.Collection;
accounts.url = '/accounts';
accounts.fetch();

How to extract a specific model from collection,and set id model

Goodmorning,i'm a bit confused about a specific id that a model has got and the id that it's has in parse.com because my collection is linked to parse.com.
If i want to get a specific model from my collection how can i do?
An example,my collection is this:
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte',
});
return Proposte;
and my model is this:
var Proposta = Backbone.Model.extend({
url:"https://api.parse.com/1/classes/Proposte",
...
If i want to get a specific model from my collection how can i do?
have a try at this:
var item = Proposte.findWhere({'url':"https://api.parse.com/1/classes/Proposte"});
hare is the doc
Edit:
The code above gives you the first matched model of the collection.
If you want to get multiple models that matches the specific attributes of a model, just use where
General case:
Define idAttribute for your Model/Collection:
var Proposta = Backbone.Model.extend({
idAttribute: 'name',
});
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte'
});
// Done here with static data just for illustration
var collection = new Proposte([{name: 'aaa'}, {name: 'bbb'}]);
Use the defined attribute to retrieve Models from collection:
console.log(collection.get('aaa'));
JSFIddle
URL, of course, can also be that attribute (just in case):
var Proposta = Backbone.Model.extend({
idAttribute: 'url'
});
var Proposte = Backbone.Collection.extend({
model:Proposta,
url:'https://api.parse.com/1/classes/Proposte',
});
var collection = new Proposte([{url: 'https://api.parse.com/1/classes/Proposte/1'}, {url: 'https://api.parse.com/1/classes/Proposte/2'}]);
console.log(collection.get('https://api.parse.com/1/classes/Proposte/2'));

How do I render multiple records out to a html table with Backbone.js ?

var ContractModel = Backbone.Model.extend({
url: "${g.createLink(controller:'waiverContract', action:'index')}"
})
var contract = new ContractModel({});
contract.fetch();
var contracts = new Backbone.Collection.extend({
model: contract
});
var ContractView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function() {
var root = this.$el;
_.each(this.model, function(item) {
var row = '<tr><td>' + item + '</td></tr>';
root.find('tbody').append(row);
});
return this;
}
});
var cView = new ContractView({ model: contract, el: $('#contracts') });
I have Chrome's developer tools open. If I do a console.log(this.model) inside of the render function, I can see a mess of an object, of which the two records are stored in .attributes. But instead of two rows being added to the table, I get 7. 6 of which are objects. (Though I see 9 subobjects in Chrome's console).
Not much of this makes sense to me. Can anyone help me not only get this working, but also understand it? I know that render() fires off as soon as I have instantiated cView, and I know that it's doing the ajax as soon as I do .fetch() into the model. But that's the limit of what I can understand in this.
You should fetch and iterate on the collection, not the model. A model is one "thing" and a collection has many "things". Assuming you are fetching a JSON formatted array into your model, it will end up with properties like "1", "2", and so on, and each of these will just be a normal Javascript object, not a ContractModel instance.
Here is how you might restructure your code:
var ContractModel = Backbone.Model.extend();
var ContractCollection = Backbone.Collection.extend({
//ContractModel class, not an instance
model: ContractModel,
//Set the url property on the collection, not the model
url: "${g.createLink(controller:'waiverContract', action:'index')}"
})
var ContractView = Backbone.View.extend({
initialize: function(){
//Bind the collection reset event, gets fired when fetch complets
this.collection.on('reset', this.render, this);
},
render: function() {
//This finds the tbody element scoped to your view.
//This assumes you have already added a tbody to the view somehow.
//You might do this with something like
//this.$el.html('<table><tbody></tbody></table>');
var $tbody = this.$('tbody');
this.collection.each(function(contract) {
//Add any other contract properties here,
//as needed, by calling the get() model method
var row = '<tr><td>' + contract.get('someContractProperty') + '</td></tr>';
//Append the row to the tbody
$tbody.append(row);
});
return this;
}
});
//Instantiate collection here, and pass it to the view
var contracts = new ContractCollection();
var cView = new ContractView({
collection: contracts,
el: $('#contracts')
});
//Makes the AJAX call.
//Triggers reset on success, and causes the view to render.
//Assumes a JSON response format like:
// [ { ... }, { ... }, ... ]
contracts.fetch();

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