Reputation: 13347
I have a backbone mobile application that is tied to a Rails web service. All models of other objects are loaded and displayed correctly, but this particular one does not. The issue I am having is that Item
gets created, but does not load the attributes. I have confirmed correct json output of the rails api. The difference between this collection and all other collections of this application is that this collection has a parentID that must be used in the url to load the correct items (category_id
).
Now... the funny thing is that if I remove the {category_id: options.attributes[0].category_id}
argument to the constructor call of ItemCollectionView
and hard code a category_id
directly into the url, it works! (however I need to assign this dynamically based on the category of the parent view.
Here are my classes:
export class ItemCollectionView extends Backbone.View {
public template: string;
public collection: itemsImport.Items;
constructor(options?: Backbone.ViewOptions){
this.collection = new itemsImport.Items({category_id: options.attributes[0].category_id});
super(options);
}
...
public addOne(item: itemImport.Item): void{
var view: itemItemImport.ItemItemView = new itemItemImport.ItemItemView({el: this.el, model: item});
//Breakpoint right here shows that item.attributes.id = undefined
view.render();
}
}
export class Items extends Backbone.Collection {
public url: string;
constructor(attributes?: any, options?: any){
this.url = 'http://localhost:3000/categories/' + attributes.category_id + '/items';
this.model = itemImport.Item;
super(attributes, options);
}
}
In my debugging I can confirm that:
options.attributes[0].category_id == 1;
and
this.url == 'http://localhost:3000/categories/1/items';
and the response from that url is:
[{"id":1,"category_id":1,"title":"Item 1","description":null,"active":true,"comment":null,"extra":null,"deleted":"0","url":"http://localhost:3000/categories/1/items/1.json"},{"id":2,"category_id":1,"title":"Item 2","description":null,"active":true,"comment":null,"extra":null,"deleted":"0","url":"http://localhost:3000/categories/1/items/2.json"}]
which you can see is a correct json response.
So my question is: What am I doing wrong? || What is the correct way to dynamically pass variables into collections to set the correct url at runtime?
Thank you for your help
Upvotes: 1
Views: 881
Reputation: 891
It is possible to define a dynamic url
property to your Backbone model in your Typescript code. This would be better than using the url
parameter in all your calls to fetch()
.
You could either do it using an ECMAScript 5 getter:
export class Items extends Backbone.Collection {
get url(): string {
return '/categories/' + this.get('category_id') + '/items';
}
constructor(attributes?: any, options?: any){
this.model = itemImport.Item;
super(attributes, options);
}
}
or by setting it directly on the prototype
:
export class Items extends Backbone.Collection {
constructor(attributes?: any, options?: any){
this.model = itemImport.Item;
super(attributes, options);
}
}
Items.prototype.url = function() {
return '/categories/' + this.get('category_id') + '/items';
};
The second solution will work on all browser.
Upvotes: 0
Reputation: 13347
The other answer selected will work if using javascript, but if using TypeScript the compiler will complain that url
must be a property, not a method. The solution I found (which will work in javascript as well) is to set the url
argument on the fetch()
method of the collection like below
export class ItemCollectionView extends Backbone.View {
public template: string;
public collection: itemsImport.Items;
constructor(options?: Backbone.ViewOptions){
this.collection = new itemsImport.Items({category_id: options.attributes[0].category_id});
super(options);
}
public initialize(options?:any): void {
this.listenTo(this.collection, 'add', this.addOne);
this.listenTo(this.collection, 'reset', this.addAll);
this.collection.fetch({url: this.collection.seturl(options.attributes[0].category_id)});
}
...
}
I hope this helps future users looking for this functionality in Backbone
Upvotes: 0
Reputation: 1553
Define url
as function like in second case here
var Notes = Backbone.Collection.extend({
url: function() {
return this.document.url() + '/notes';
}
});
And check network tab if you really load correct url.
Upvotes: 1