Get entire model in Backbone JS - javascript

In backbone javascript models, we get individual items as shown below:
var type = this.model.get("type");
Here, type will be defined in server side & then fetched in JS using above syntax.
My question is how do I get the entire model in one shot?
I tried this.model.toString() but it prints [object object]
Any suggestion?
EDIT: I'm using above line of code in backbone view & not the model. And in this view, I need to read all the models data even if its JSON string, thts fine with me. How do I get it. I don't want to use separate collection or anything else. I need to update the above view only to get entire model.

You can use model.toJSON() to get all the attributes of a model.

you use a collection
http://backbonejs.org/#Collection
You can then iterate though the collection to obtain each model.
var Library = Backbone.Collection.extend({
model: Book
});
for example and then
books = new Library();
books.each(function(book) {
book.publish();
});
to iterate

Related

Creating and updating nested objects in Ember

I got nested JSON data from the server like this:
{
name: "Alice",
profile: {
something: "abc"
}
}
and I have the following model:
App.User = Ember.Object.extend({
name: null,
profile: Ember.Object.extend({
something: null
})
})
If I simply do App.User.create(attrs) or user.setProperties(attrs), the profile object gets overwritten by plain JS object, so currently I'm doing this:
var profileAttr = attrs.profile;
delete attrs.profile
user.setProperties(attrs); // or user = App.User.create(attrs);
user.get('profile').setProperties(profileAttrs);
It works, but I've got it in a few places and in the real code I've got more than one nested object, so I was wondering if it's ok to override User#create and User#setProperties methods to do it automatically. Maybe there's some better way?
Based on your comment, you want the automatic merging behaviour you get with models (the sort of thing you get with .extend()). In that case, you could try registering a custom transformer, something like:
App.ObjectTransform = DS.Transform.extend({
deserialize: function(json){
return Ember.Object.create(json);
}
});
App.User = DS.Model.extend({
profile: DS.attr('object')
});
See: https://github.com/emberjs/data/blob/master/TRANSITION.md#json-transforms
If you are doing your server requests without an adapter you can use the model class method load() with either an array of json objects or a single object. This will refresh any known records already cached and stash away the JSON for future primary key based lookups. You can also call load() on a model instance with a JSON hash as well but it will only update that single model instance.
Its unclear why you are not using an adapter, you can extend one of the Ember Model adapters and override the the record loading there, eg. extend from the RESTAdapter and do any required transform on the JSON if required by overriding _loadRecordFromData
You can also override your models load function to transform data received if required as well. The Ember Model source is fairly easy to read so its not hard to extend to your requirements.

Newly saved Backbone model does not appear in collection after fetch

I am using backbone local storage and experiencing some weird behavior.
I have a Model and Collection that is defined, instantiated, and fetched:
MyModel = Backbone.Model.extend({
localStorage: new LocalStore('example-myModels')
//note: LocalStore = Backbone.LocalStore -> https://github.com/jeromegn/Backbone.localStorage
});
MyCollection = Backbone.Collection.extend({
model : MyModel,
localStorage: new LocalStore('example-myModels')
});
var myCollection = new MyCollection();
myCollection.fetch(...);
This collection is then displayed as a list to the user. The user is able to "add" an item to the collection which eventually results in this code:
var newModel = new MyModel();
newModel.save(newModelAttributes, {
success: function(newlySavedModel) {
myCollection.add(newlySavedModel);
}
);
At this point myCollection has the newly added model and I can see the record successfully created in my localStorage database:
Pre-save LocalStorage:
Post-save LocalStorage:
The next step after the user adds the record is to go back to the list, at which point the collection is fetched again:
myCollection.fetch();
Now myCollection no longer contains the new record. No matter how many times I fetch, the new record will not be retrieved - even though I can see it in my localStorage database. I have also tried creating a new instance of the Collection and fetching that but it yields the same results. If I reload the browser, the new record appears as expected. Anyone have any idea what is going on? I get the feeling I am missing something fundamental here...
A running example that reproduces the issue is available here: http://jsbin.com/iyorax/2/edit (make sure the console is visible and click "Run with JS")
Thanks in advance!
Your model and your collection need to share a reference to the same instance of LocalStore, whereas right now you are creating two different objects. To fix this, create the LocalStore object outside of either model or collection, and pass in a reference to it in the constructors of your Model and collection.
I have an application working with Backbone.localstorage and what works for me is I first add the model to the collection and then I call save to the model. like this.
var newModel = new MyModel();
myCollection.add(newModel)
newModel.save();
Im not 100% sure, but my reasoning is that, your model is saved, but your collection is not, and perhaps an index is not being updated and at the time that you call fetch you are getting the unupdated collection.
Hope that helps.
The only reason I can think of due to which the model is not present in the collection is because of Duplicated ID's
I don't see a IdAttribute defined on the model. That could be a problem sometimes.

Saving and restoring an observableArray containing nested observableArrays

I have a model which I need to save to JSON and re-load as required. The idea is that the user can save the model to a basket or database (as a JSON string) and then reload it. It's simple enough to create the JSON and save it but re-loading is seemingly much more difficult. The problem is that my model includes some complex objects similar to the Knockout Contacts example:
http://knockoutjs.com/examples/contactsEditor.html
I can even generate the JSON and pass it via a web service into an .NET object.
I've looked at the Knockout documentation for loading a data model:
http://knockoutjs.com/documentation/json-data.html
...and I can easily restore my "simple" observables but I don't see how I can initialise my arrays of complex objects where these objects also contain observable arrays. Any ideas?
I've even tried using the mapping plugin but the resulting JSON doesn't contain the information in the arrays.
Doing this creates the JSON and all my data is in there:
var jsonData = JSON.stringify(ko.toJS(self.contacts), null, 2)
Ideally, I just need to reverse this or at least create all the objects one by one.
Thanks for looking :)
The mapping plugin should work. I'm not sure if i understood correctly your situation, but try somethig like that:
ViewModel = function() {
this.contacts = ko.observableArray();
}
var model = new ViewModel();
ko.applyBindings(model);
var json = '{"contacts":[{"name":"Tom","phones":["00000000","1111111111"]},{"name":"Bill","phones":["222222222","333333333"]},{"name":"Bert","phones":["444444444","55555555"]}]}';
ko.mapping.fromJSON(json, {}, model);
The observableArray of "contacts" and "phones" in each contact are deserialized correctly from the json string.
http://jsfiddle.net/k4Sth/1/

How to get/parse data from Backbone.LocalStorage

I am trying to understand how Backbone.LocalStorage is used the from the following jagin/todos.
Referring to the Backbone.Marionette doc, In order to render the list of todos, it should be enough to make the following code:
new CompositeView({
model: someModel,
collection: someCollection,
itemView: RowView
});
So, referring to the jagin/todos the collection should be an object fetched from the backbone.localstorage.
My question is:
I would like to get this collection/models from the javascript console.
I did try the following but it returns an object which is different from a backbone.collection.
new Backbone.LocalStorage("todos-marionette");
// {"name":"todos-marionette","records":["1244f588-be3d-c493-5c86-b2abb997af82"]}
Any ideas?

Persisting & loading metadata in a backbone.js collection

I have a situation using backbone.js where I have a collection of models, and some additional information about the models. For example, imagine that I'm returning a list of amounts: they have a quantity associated with each model. Assume now that the unit for each of the amounts is always the same: say quarts. Then the json object I get back from my service might be something like:
{
dataPoints: [
{quantity: 5 },
{quantity: 10 },
...
],
unit : quarts
}
Now backbone collections have no real mechanism for natively associating this meta-data with the collection, but it was suggested to me in this question: Setting attributes on a collection - backbone js that I can extend the collection with a .meta(property, [value]) style function - which is a great solution. However, naturally it follows that we'd like to be able to cleanly retrieve this data from a json response like the one we have above.
Backbone.js gives us the parse(response) function, which allows us to specify where to extract the collection's list of models from in combination with the url attribute. There is no way that I'm aware of, however, to make a more intelligent function without overloading fetch() which would remove the partial functionality that is already available.
My question is this: is there a better option than overloading fetch() (and trying it to call it's superclass implementation) to achieve what I want to achieve?
Thanks
Personally, I would wrap the Collection inside another Model, and then override parse, like so:
var DataPointsCollection = Backbone.Collection.extend({ /* etc etc */ });
var CollectionContainer = Backbone.Model.extend({
defaults: {
dataPoints: new DataPointsCollection(),
unit: "quarts"
},
parse: function(obj) {
// update the inner collection
this.get("dataPoints").refresh(obj.dataPoints);
// this mightn't be necessary
delete obj.dataPoints;
return obj;
}
});
The Collection.refresh() call updates the model with new values. Passing in a custom meta value to the Collection as previously suggested might stop you from being able to bind to those meta values.
This meta data does not belong on the collection. It belongs in the name or some other descriptor of the code. Your code should declaratively know that the collection it has is only full of quartz elements. It already does since the url points to quartz elements.
var quartzCollection = new FooCollection();
quartzCollection.url = quartzurl;
quartzCollection.fetch();
If you really need to get this data why don't you just call
_.uniq(quartzCollecion.pluck("unit"))[0];

Categories