Backbone Fetch not by ID - backbone.js

is it possible to fetch on backbone, by a different attribute?
Now I can only fetch by ID which will return /url/IDVALUE
is is possible to do
model.fetch({name:'VALUE'});
and then it will generate the /url/NAMEVALUE ?
Thanks.

this is a workaround and I think you should use this just to do the fetch but I think it can work
change the IdAttributte and use the name,
then when you fetch your model the url will use the name attribute
http://backbonejs.org/#Model-idAttribute
var Model = Backbone.Model.extend({
idAttribute: "name"
});

Related

Backbone.js: Natively passing attributes to models when fetched with a collection

Let say you are defining a Backbone.js Model. From the documentation we have ...
new Model([attributes], [options])
This seems great for passing some default attributes to a model. When passed the model automatically inherits those attributes and their respective values. Nothing to do. Awesome!
On they other hand lets say we have a Collection of that model.
new Backbone.Collection([models], [options])
Okay, cool we can pass some initial models and some options. But, I have no initial models and no options I need to pass so let's continue. I am going to fetch the models from the server.
collection.fetch([options])
Well I don't have any options, but I want to pass some attributes to add to each models as it is fetched. I could do this by passing them as options and then adding them to the attributes hash in the initialize for the model, but this seems messy.
Is their a Backbone.js native way to do this?
You can pass the attributes as options to fetch and over-ride the collection's parse method to extend the passed options (attributes) on the response.
The solution would look like the following:
var Collection = Backbone.Collection.extend({
url:'someUrl',
parse:function(resp,options) {
if (options.attributesToAdd) {
for (var i=0;i<resp.length;i++)
_.extend(resp[i],options.attributesToAdd);
}
return resp;
}
});
Then to add attributes when you call fetch on the collection, you can:
var collection = new Collection();
collection.fetch({
attributesToAdd:{foo:'bar',more:'foobar'}
});
You may have to tweak the code a bit to work with your JSON structure, but hopefully this will get you started in the correct direction.

How to update model in collection?

I have the following Backbone.js collection:
var Tags = Backbone.Collection.extend({
url: "/api/v1/tags/"
}),
How do I update one of the models in the collection so that it posts to /api/v1/tags/id and saves the data for that model.
So if I change name of model with id 2 in the collection
It should PUT to
/api/v1/tags/2 with the following data:
name: new name id: 2
I've also recently wanted to update particular model in the collection. The problem was that if I did use just model.save it didn't update the collection. The goal was to change the model in collection, change it on the server, update collection accordingly and not use the sync method. So for example I have my variable collection and I want to change the model with id = 2. So the first thing, I will create an instance model, like this: var model = collection.get(2)Then I will update the attributes on this particular model:model.set({name: 'new name'})Then I will save it to the server:model.save({}, {url:'/api/v1/tags/'+model.get('id')})Then we have to update collection accordingly to the changes:collection.set({model},{remove: false})set method - it's a 'smart' update of the collection with the list of the models you passed in parameters. remove: false parameter - it's a restriction for a collection to remove existing models in collection. More here.
The first thing you can miss is that in your corresponding Tag model you'll need to set "urlRoot" to match the Collection's "url". Otherwise it doesn't know about the collection at all:
var Tag = Backbone.Model.extend({
urlRoot: "/api/v1/tags"
});
var Tags = Backbone.Collection.Extend({
model: Tag,
url: "/api/v1/tags"
});
This is useful if you want to save the tag separately:
var tag = collection.get(2);
tag.set({key: "something"});
tag.save(); // model.save works because you set "urlRoot"
On the collection, "create()" is also "update()" if id is not null. That's not confusing. :) Therefore, this is pretty much equivalent to the previous sample:
collection.create({id: 2; key: "something"});
This will update the existing tag with id=2 and then trigger a PUT.
This is an ancient question; answering because I was searching for the same answer--you've probably long since solved this problem and moved on. :)
You can pass variables to the save method. It accepts all the options which jQuery's ajax method uses (unless you overrided Backbone.Sync)
You could do something like:
model.save( { name:'new name' } );
The id and PUT method will automatically be added by Backbone for you.

When to use URL attribute for both Collection and Model?

I've been following some Backbone.js tutorials and am a bit confused about when to use 'url' inside Model when there is also a Collection which contains the model. For example I see a lot of code that looks like this, in order to synchronize with the server:
var PostModel = Backbone.Model.extend({});
var PostsModel = Bacbone.Collection.extend({
model: PostModel,
url: "/posts"
});
However I also see some where the model also has 'url' property, like so:
var PostModel = Backbone.Model.extend({
url: "/posts"
});
var PostsModel = Bacbone.Collection.extend({
model: PostModel,
url: "/posts"
});
I think I understand the first method, where I interact with the models only through the collections to which they belong, but I am not sure when you would want to have urls for both a model and its collection.
Sometimes you need a model that doesn't belong to any collection.
For example a login/sign in.
var LoginModel = Backbone.Model.extend({
url: "/login"
});
This way you can interact with login view and model just like you would with any other Backbone model, including save() (which posts the login form to the server) and validation.
There is however no login collection, so it doesn't make sense to model that.
Maybe the code you're seeing is something in between. Models are accessed via collection in some places of the application and without collection in others.
If it's a good design is another story, but there's no technical reason to not do it.
edit
As you noticed, using urlRoot is another option, since by default the url attribute is a method that uses urlRoot to construct the relative url.
It can be, however, given a string value to specify the model url directly.

Backbone Collection - Model Update

I retrieve a list of models from server into a collection. When a user is interested in a specific model, I route it to a viewer for that model based on the id.
Now, let's say a user need edits to that model in the view - eg: he updates his name. I set the url of the model, update the name and call save. It calls the backend (Jersey in my case) and it gets saved. However, the collection is still not updated automatically.
Why cannot a collection bind to each change in the model and update it self?
What is the correct way of saving a model which is a part of the collection? Is it right to call save on a model (by setting its url) and then remove from its parent collection and then add it again with silent:true?
Thanks.
The Collection is not updated?
When you say "the collection is not updated automatically" I guess you mean "the View is not updated automatically".
The View will not respond to Model changes at least you say so explicitly using bindings:
// code simplified and no tested
var MyModel = Backbone.Model.extend({});
var MyModelView =
Backbone.View.extend({
initialize: function(){
this.model.on( "change:all", this.render, this );
},
render: function(){
this.$el.html( "<h1>" + this.model.title + "</h1>" );
}
})
Declare the URL explicitly for each Model
As #OlliM has said, this shouldn't be necessary if your backend is supporting an standard CRUD API. You can declare the URL in your Collection like this:
/app/collection
And Backbone will use this URLs as the API:
(GET) /app/collection fetch the whole Collection
(GET) /app/collection/1 fetch only the Model with id = 1
(PUT) /app/collection/1 update the Model with id = 1
(POST) /app/collection create a new Model
... DELETE and so on

Backbone.js sents POST instead of PUT (mongoose set _id to id)

Backbone.js sents an POST on updated objects instead of an PUT.
I think this is because mongoDB uses _id instead of id.
How do I say backbone.js to use _id instead of id?
I already tried some server-side change but I think it would be easier just to say that backbone should use another attribute as id.
MongoDB: output 'id' instead of '_id'
From the fine manual http://backbonejs.org/#Model-idAttribute
idAttribute model.idAttribute
A model's unique identifier is stored under the id attribute. If you're directly communicating with a
backend (CouchDB, MongoDB) that uses a different unique key, you may
set a Model's idAttribute to transparently map from that key to id.
Id attribute can be changed per model like
var Meal = Backbone.Model.extend({
idAttribute: "_id"
});
To make it default for all models (eg., if we are using mongodb), override the default setting by placing this LOC in your app js file that runs after backbone.js
//override the id attribute for model
Backbone.Model.prototype.idAttribute = '_id';

Resources