From the Backbone.js (1.2.3) documentation:
add collection.add(models, [options])
Add a model (or an array of models) to the collection, firing an "add" event for each model, and an "update" event afterwards.
In my code I want to add a new model (visually a card with an input) to the collection and then force focus on the input of created card. I'm not sure if it's the correct way, but I basically listen to the event fired when model is added to collection and trigger another event which facilitates focusing from the view of created model:
# ItemView
initialize: ->
App.vent.on "focus:field", =>
$("div.card:last").addClass("edit")
@$el.find("input:first").focus()
When I listen to the update
event, it works as expected: :last
card (the new model) is selected and input is focused.
But when I listen to the add
event, initialize
function fires on the penultimate model, instead of the new model. The new model is still created, but the edit
class and focus is forced on the one before.
Why is that happens?
I would use an update
event for this purpose, but unfortunately for me model.destroy
method also fires an update
event, so it results in ruined UI, and if I pass model.destroy
with silient:true
bad things happen overall. Is there a workaround?
Relevant code:
# CompositeView
class List.Models extends App.Views.CompositeView
template: "path/to/template"
childViewContainer: "div.destination"
childView: List.Model
events:
"click #add-model": "addModel"
initialize: ->
@listenTo @collection, "update", ->
App.vent.trigger "focus:field"
addModel: (e) ->
@$el.find("#add-model").prop "disabled", true
model = App.request "new:model:entity"
@collection.add(model)
# ItemView
class List.Model extends App.Views.ItemView
template: "path/to/template"
initialize: ->
App.vent.on "focus:field", =>
$("div.card:last").addClass("edit")
@$el.find("input:first").focus()
Edit:
Apparently the difference between add
and update
events is that the add
event is fired immediately after @collection.add(model)
is called, but before new model is inserted in the DOM, resulting in $("div.card:last")
selector pointing to the penultimate view. I'm not sure however, maybe more experienced people can clarify whether this is true or not. I've come to this conclusion after adding timeout to the execution of the App.vent:
initialize: ->
delay = (ms, func) -> setTimeout func, ms
# Triggered via add event
App.vent.on "focus:field", =>
delay 100, =>
$("div.card:last").addClass("edit")
$("input:first").focus()