Reputation: 821
In my Backbone view here, I want to be able to immediately add my model to my collection with an 'id'
attribute included in the newly created model. In other words, I need to have access to this 'id'
right away. With the id
available, my removeCategory
method can work. To "solve" that problem, I tried to add the line this.collection.fetch()
directly below this.collection.add(model);
, but it gave me very bad UI (the new <li>
wouldn't even render, etc), plus it seems like very bad coding practice anyway.
I'm relatively new with Backbone, so I'm not sure if create
(save/add) should automatically add the model to the collection with an id
or not. If it should, then there must be something wrong with the JSON data I'm receiving from my Rails RESTful API. If create
does NOT do that, then how can I instantly get access to this specific newly created model, with an id
(other than by refreshing the browser -- ugh!)? I need the id
for <li data-id={{id}}></li>
in my Handlebars template as soon as I invoke the "addCategory" method.
Also (& this might be a related problem), when I do model.fetch();
, I get back the model's entire collection, plus that newly-created server-side model without an id
. Any help on this would be much appreciated.
window.CategoriesView = Backbone.View.extend({
index_template: HandlebarsTemplates['categories/index'],
events: {
'click .delete': 'removeCategory',
'click .category_add': 'addCategory'
},
initialize: function() {
_.bindAll(this, 'render');
this.collection.fetch();
this.listenTo(this.collection, 'all', this.render);
},
show: function() {
$("#categorymodal").modal();
},
addCategory: function(e) {
e.preventDefault();
// I wrote the next three lines here explicitly rather than using 'create'
var model = new Category({ name: $(this.el).find('.category_name').val() });
model.save();
this.collection.add(model);
this.show();
},
removeCategory: function(e) {
e.preventDefault();
var id = $(e.target).parents('li').data('id');
var model = this.collection.where({ id: id })[0];
this.collection.remove(model);
if (model) { model.destroy(); }
this.render();
},
render: function() {
$(this.el).html(this.index_template());
this.collection.models.forEach(function(cat) {
var li_template = HandlebarsTemplates['categories/show']
$(this.el).find('.categories').append(li_template({
id: cat.toJSON().id,
name: cat.toJSON().name
}));
}, this);
return this;
}
});
Here is my #create
action in Rails....
def create
@category = Category.create(category_params)
render :nothing => true
end
I am using jbuilder
to provide the JSON from the Rails API.
Here is my Backbone model and collection...
window.Category = Backbone.Model.extend({
urlRoot: "categories"
});
window.Categories = Backbone.Collection.extend({
model: Category,
url : function() {
return 'categories';
}
});
Upvotes: 0
Views: 157
Reputation: 821
I figured out my problem. It was in my Rails controller, not with Backbone create
. I changed my #create
action from this...
def create
@category = Category.create(category_params)
render :nothing => true
end
...to this....
def create
@category = Category.create(category_params)
redirect_to category_path(@category)
end
...with my show action being this...
def show
@category = Category.find(params[:id])
end
...that provided me with http://localhost:3000/categories/752.json
. I've gotta make sure my backend is providing what I need JSON-wise!
Upvotes: 1