0

First of all I have read about Event Delegation in several stackoverflow posts and articles like this: Understanding Event Delegation, and it makes sense, it just isn't working in this instance. I am working on a Rails 3 application. I have a nested form using the simple_nested_form gem that submits a new record via ajax and upon success, renders a partial containing new record(s) and the form on a #show template. The design requires: The user arrives on the page and can see the records (if there are any) and a button to Enter/Edit Timecard. The button will toggle between showing the records or the form, but not both. This works fine. The user clicks the button, is presented with the form, then adds, updates or deletes a record. They click submit, the ajax updates the page, but now the Enter/Edit Timecard button no longer works. The following is edited for brevity.

The partial rendered in the show template

<div id="update-timecard-area">
  <div id="timecard-partial">
    <%= render partial: 'timecards'%>
  </div>
</div>

The contents of the partial

<div id="timecard-display-area">
 # Display records
</div>

<div id="timecard-form-area" >
  # The from
</div>

<div>    
  # Link that when clicked either displays the form or the records but not both
  <a href="#" id="toggle-timecard-form" class='btn btn-default btn-sm'>Enter/Edit Timecard</a>
</div>

Relevant SCSS that hides the form on initial page load

#update-timecard-area {
  #timecard-form-area {
    display: none;
  }
}

Function that hides/shows parts of the form

$( document ).ready(function($) {
  $("#timecard-partial").on( "click", "a#toggle-timecard-form", function(e) {
    e.preventDefault();

    if ($("#timecard-display-area").is(":visible")){
        $("#timecard-display-area").hide();
        $("#timecard-form-area").show();
    }
    else if ($("#timecard-form-area").is(":visible")) {
        $("#timecard-display-area").show();
        $("#timecard-form-area").hide();
    }
  });
});

2 Answers2

1

That's because you're performing your event bindings on those specific elements and those elements are replaced when you re-render the partial.

I'd suggest encapsulating all of your binding code into a function then calling that after the partial is rendered.

For example:

function setup($) {
    $("#timecard-partial").on( "click", "a#toggle-timecard-form", function(e) {
        e.preventDefault();

        if ($("#timecard-display-area").is(":visible")){
            $("#timecard-display-area").hide();
            $("#timecard-form-area").show();
        }
        else if ($("#timecard-form-area").is(":visible")) {
            $("#timecard-display-area").show();
            $("#timecard-form-area").hide();
        }
    });
}

$( document ).ready(setup);

Then you can call setup() whenever the partial is rendered.

Mike Cluck
  • 28,921
  • 12
  • 72
  • 85
  • How do I tell if the partial has been rendered? I have tried things like [this](http://stackoverflow.com/questions/18518990/rails-4-how-to-catch-ajaxsuccess-event) but no luck. – NickTerrafranca Jan 28 '16 at 01:18
0

I suspect that after the form submits you are messing with the #timecard-partial. You can try this:

$( document ).ready(function($) {
  $("body").on( "click", "a#toggle-timecard-form", function(e) {
    e.preventDefault();

    if ($("#timecard-display-area").is(":visible")){
        $("#timecard-display-area").hide();
        $("#timecard-form-area").show();
    }
    else if ($("#timecard-form-area").is(":visible")) {
        $("#timecard-display-area").show();
        $("#timecard-form-area").hide();
    }
  });
});

Here we are binding on the body instead of the #timecard-partial

DevMarwen
  • 1,626
  • 11
  • 27