Your problem is right here:
$('#main-container').html(@view_new.render(url_step_number).el)
From the fine manual:
.html( htmlString )
[...]
When.html()
is used to set an element's content, any content that was in that element is completely replaced by the new content. Additionally, jQuery removes other constructs such as data and event handlers from child elements before replacing those elements with the new content.
Note the removes other constructs such as data and event handlers part. The sequence of events goes like this:
- You call
render
. render
callsdelegateEvents
to attached a jQuery event delegator to the view'sel
.- You call
$x.html(view.el)
butview.el
is already there so jQuery detaches all the event bindings (including the one you just added in 2), clears out$x
, and then putsview.el
back into$x
.
But when view.el
is put back on the page, the events are already gone. This is roughly equivalent to what you're doing:
# In the view...
add_step: ->
re_render(@step_number + 1)
and
v = new YourView
$('#main-container').append(v.render(1).el)
re_render = (step_number) ->
$('#main-container').html(v.render(step_number).el)
Demo: http://jsfiddle.net/ambiguous/4rJyB/
You need to stop calling .html
all the time. Once the view is on the page, you can simply tell it to re-render itself and that's all you need to do. So, if the view has been rendered once to get its el
into #main-container
, you just need to:
@view_new.render(url_step_number)
and that's it. Then you can remove the @delegateEvents
call from render
and use the usual events map on the view:
class MyApp.Views.ChainsNew extends Backbone.View
events:
'click #btn-go': 'add_step'
render: (step_number) ->
window.model = @model
@step_number = step_number
@template = if @step_number is 1 then JST['chains/new'] else JST['chains/step']
@$el.html(@template())
@
#...