0

I can't figure out how to add event handlers to dynamically added html in the fiddle example below. Through searching I realize you have to delegate the handler to an element originally on the page. However, I am passing the newly added elements into a module (dateTimeRangeWidget) that sets everything up.

https://jsfiddle.net/burtonrhodes/u2L2epmz/

html

<h3>
  Date Picker Test
  <a href="#" id="do_addEvent" class="btn btn-warning pull-right">
    Add Event
  </a>
</h3>
<hr/>

<form>

  <div class="eventsDiv">

    <!-- Event[0] -->
    <div class="eventDiv" data-id="0">
      <div class="row">
        <div class="form-group col-xs-3">
          <label>Start Date</label>
          <input type="text" name="event[0].startDate" class="form-control startDate">

          <div class="checkbox">
            <label>
              <input type="checkbox" name="event[0].allDayEvent" class="allDayEvent" /> 
              All Day Event
            </label>
          </div>
        </div>

        <div class="form-group col-xs-3 timeDiv">
          <label>Start Time</label>
          <input type="text" name="event[0].startTime" class="form-control startTime">
        </div>
        <div class="form-group col-xs-3">
          <label>End Date</label>
          <input type="text" name="event[0].endDate" class="form-control endDate">
        </div>

        <div class="form-group col-xs-3 timeDiv">
          <label>End Time</label>
          <input type="text" name="event[0].endTime" class="form-control endTime">
        </div>
      </div>
      <hr/>
    </div>

  </div>
  <!-- ./eventsDiv -->
</form>

js

$(document).ready(function() {

  // Wire do_addEvent button
  $("#do_addEvent").on("click", function(event) {

    // Copy and add evenDiv html at the bottom
    var lastEventDiv = $("div.eventDiv").last();
    var newEventDiv = $(lastEventDiv).after($(lastEventDiv).html());

    // TODO rename input variable names here with newId
    // --- code here --

    // Setup the new eventDiv
    // !!! This doesn't work !!!
    setUpEventDiv(newEventDiv);

    event.preventDefault();
  });

  // Setup all eventDiv's when the page loads
  $("div.eventDiv").each(function(index, eventDiv) {
    // Wire the eventDiv
    setUpEventDiv(eventDiv)
  });

});

/**
 * Finds all the div elements and calls setupDateTimePicker
 */
function setUpEventDiv(eventDiv) {
  var $startDateTextBox = $(eventDiv).find('.startDate:first').datepicker();
  var $endDateTextBox = $(eventDiv).find('.endDate:first');
  var $startTimeTextBox = $(eventDiv).find('.startTime:first');
  var $endTimeTextBox = $(eventDiv).find('.endTime:first');

  var $allDayEventCheckBox = $(eventDiv).find('.allDayEvent:first');
  var $timesDiv = $(eventDiv).find('.timeDiv');

  // Setup time picker
  setupDateTimePicker($startDateTextBox, $startTimeTextBox,
    $endDateTextBox, $endTimeTextBox,
    $allDayEventCheckBox, $timesDiv);
}

/**
 * Sets up the custom date/time picker widget
 */
function setupDateTimePicker($startDate, $startTime,
  $endDate, $endTime,
  $allDayEvent, $timesDiv) {

  var mydtrw = dateTimeRangeWidget(jQuery);
  mydtrw.init({
    $startDateElem: $startDate,
    $endDateElem: $endDate,
    $startTimeElem: $startTime,
    $endTimeElem: $endTime,
    $allDayEventElem: $allDayEvent,
    $timeElements: $timesDiv
  });
}
VVV
  • 7,288
  • 3
  • 30
  • 53
Burton
  • 589
  • 5
  • 11
  • I know this question got closed and it shouldn't have been closed because it's not a duplicate... It's just the title that's misleading. Anyway, I fixed your code. It's available here: https://jsfiddle.net/u2L2epmz/14/ – VVV Nov 29 '16 at 15:04
  • Thank you!! Question: what is the point of "$(element).removeClass('hasDatepicker')" line? – Burton Nov 29 '16 at 17:00
  • I think the datePicker plugin determines if the element is already initialized by using that class. If you don't remove that class, the element never initializes and you can't choose a date. When I removed the class, everything worked. Hope it helps. Let me know if you have comments. I can explain why your code didn't work. – VVV Nov 30 '16 at 15:58
  • @RoryMcCrossan I don't believe this question should be closed. Only the title is misleading but in fact there is lots of jquery knowledge in the answer I can provide since it has nothing to do with binding elements. Could you please review your decision? Thank you. – VVV Nov 30 '16 at 16:01
  • Updated fiddle with comments in the code: https://jsfiddle.net/u2L2epmz/15/ – VVV Nov 30 '16 at 16:07
  • fair point, I re-opened the question. @Burton please edit the title to something more relevant to the problem – Rory McCrossan Nov 30 '16 at 16:43

1 Answers1

0

There was some mistakes in your code.

When you did this $(lastEventDiv).html() you're actually stripping the parent html element so you always had just one .eventDiv

Here's a working fiddle.

$(document).ready(function() {

  // Wire do_addEvent button
  $("#do_addEvent").on("click", function(event) {

    // Copy and add eventDiv html at the bottom
    var lastEventDiv = $("div.eventDiv").last();
    var newEventDiv = lastEventDiv.clone(); //clone the last event div. When you were adding it with .html(), you were removing the parent tags so you never had a second .eventDiv.

    var newId = $("div.eventDiv").length; //lets get a unique ID. This should change in your code for something better.
    newEventDiv.data('id', newId); //change id

    //change the id and name atributes for it to work correctly
    $.each(newEventDiv.find('input'), function(index, element) {
        $(element).attr('id', 'input' + Math.round(Math.random()*100));
      $(element).attr('name',$(element).attr('name').replace(/\[\d+](?!.*\[\d)/, '[' + newId + ']'));
      $(element).removeClass('hasDatepicker'); //remove the hasDatepicker class for the plugin to work correctly.
    })

    lastEventDiv.after(newEventDiv); //append id after the last event div

    // TODO rename input variable names here with newId
    // --- code here --

    // Wire the new eventDiv date/time picker
    // !!! This doesn't work !!!

    setUpEventDiv(newEventDiv);

    event.preventDefault();
  });

  // Loop through event divs and wire actions for each section
  $("div.eventDiv").each(function(index, eventDiv) {
    // Wire the eventDiv
    setUpEventDiv(eventDiv)
  });

});
VVV
  • 7,288
  • 3
  • 30
  • 53