3

I'm using brunch to work with backbone and I'm having issues with event.preventdefault(). It works initially, but after a page change it stops working.

I have a view that passes a param to the template and according to that the page is rendered. This page has multiple forms, and loads up one according to the param. All the forms have preventdefault bound to the submit buttons, but for some reason, after I switch forms using one of the nav links, the preventdefault stops working and the form gets posted. Any idea why this is the case? Let me know if you need to see code.

An example of how this happens: I click 'submit story' nav link and type something and hit submit. I get the js alert and nothing happens. Now I click 'submit poem' and click submit, but this time the form gets posted. If I started off with 'submit poem' it works fine. It also works if I click 'submit poem' and hit refresh before submitting. Weird....

EDIT: Added Code Sample. Template renders acording to the passed in type.

class exports.ClientsSettingsView extends UberView
  id: 'settings_view'
  className: 'view_container'

  events:
    'submit #credit_card_form' : 'addCard'
    'submit #profile_pic_form' : 'processPicUpload'
    'submit #edit_info_form' : 'test'
    'click #delete_card' : 'deleteCard'


  render: (type="info",status=0) ->
    $('.spinner#submit').hide()
    @ReadUserInfo()
    $(@el).html clientsSettingsTemplate {type,status}
    @FadeIn()

    @

  addCard: (e) ->
    e.preventDefault()
    $el = $(e.currentTarget)  


    attrs = 
      card_number: $el.find('#card_number').val()
      card_code: $el.find('#card_code').val()
      card_expiration_month: $el.find('#card_expiration_month').val()
      card_expiration_year: $el.find('#card_expiration_year').val()


    options = 
      success: (response) ->
        alert "Added"      
      error: (e) ->
        alert "Error"

    model = new app.models.paymentprofile

    model.save attrs, options
    console.log attrs
userinev
  • 75
  • 1
  • 5
  • 16

2 Answers2

1

I had the same problem.

A workaround
is to manually call delegateEvents() after the Backbone.View is added to the DOM.

The issue
I was calling subview.remove() which removes all DOM event listeners (via jQuery.remove) and used that same subview instance later on.

A solution If a View has to remain active but must be temporary hidden use this.$el.hide() & this.$el.show()

In other situations don't reuse Backbone.View instances, but instantiate new ones.

Bob Fanger
  • 28,949
  • 7
  • 62
  • 78
1

How are you loading the additional forms and submit buttons later on? if you are dynamically pulling them in, your event may no longer be attached. You could try binding your event to the form submit using jquery's live method.

.live()

ryanmarc
  • 1,670
  • 1
  • 10
  • 9
  • Doesn't seem to work. This shouldn't be an issue since the view constructor calls this every time the view is loaded. – userinev Jul 11 '11 at 18:24
  • I must have misread your question originally, I updated my answer with a possible solution that is more inline with what you are explaining. If that doesn't work, you should include some code snippets to give a little bit of insight on how you have things set up and what is going on. – ryanmarc Jul 12 '11 at 18:43
  • Sweet! Using live fixed the issue. I think it was because of the dynamic insertion/replacement. Not sure how to make backbone do it automatically though... – userinev Jul 15 '11 at 23:43
  • accept the answer? It may help other people when they are searching for a similar issue. – ryanmarc Jul 22 '11 at 15:22
  • I had it accepted, until I realized that delegate events is a special form of .live(). I'm not sure why it doesn't work when I call that, but works with live called directly. I was hoping that someone else might know what was going on if I opened up the question again,. – userinev Jul 23 '11 at 01:23
  • I believe the difference is that live continuously polls watching for matched elements and attaching the event when they are found, while delegate events is a one time call to attach your events to the dom elements that exists on the page. It's also possible that it is related to how jquery injects the new dom elements and backbone not seeing them right away. If you can post some of your code showing how you create the dynamic items and where you are calling delegate events I may be able to help more. These just a couple places i'd look at to begin debugging. – ryanmarc Jul 25 '11 at 18:15
  • Just added the code sample. The form is a standard html form, nothing fancy/crazy. – userinev Jul 26 '11 at 20:38
  • After reading http://stackoverflow.com/questions/4579117/jquery-live-vs-delegate I am even more convinced that this is a backbone issue. – userinev Jul 26 '11 at 21:49