1

I've been researching this for a day and I can't quite make out what is going on. I have this program that I'm using that is dynamically adding a link if the user clicks on a button to add or delete. The add function with this listener works brilliantly.

    $(".add-row").on('click', function() {
      console.log("Test");
    });
  });

Now the same program generates a delete link....and I am purposefully hiding the first iteration of this button with a .remove in the code below...

  $(document).ready(function (){
     $(".delete-row").first().remove();
  });

Again works brilliantly. However when I try to do something like...

    $(".delete-row").on('click', function() {
      console.log("Test");
    });
  });

Nothing happens. No log nothing. If I remove...

  $(document).ready(function (){
     $(".delete-row").first().remove();
  });

Then I can get this to fire once....

    $(".delete-row").on('click', function() {
      console.log("Test");
    });
  });

I have tried several iterations of listeners...I've read about how some events if they are generated as strings won't be recognized by listeners....I've seen some references that links can be tricky with listeners....

This is the section of the program that I am using that has to do with the delete function....

/* Indicates whether delete link(s) can be displayed - when total forms > min forms
 */
showDeleteLinks = function() {
    return minForms.length == 0 || // For Django versions pre 1.7
      (minForms.val() == '' || (totalForms.val() - minForms.val() > 0));
  },

  insertDeleteLink = function(row) {
    var delCssSelector = $.trim(options.deleteCssClass).replace(/\s+/g, '.'),
      addCssSelector = $.trim(options.addCssClass).replace(/\s+/g, '.');

    var delButtonHTML = '<a class="' + options.deleteCssClass + '" id=myBtn href="javascript:void(0)">' + options.deleteText + '</a>';
    if (options.deleteContainerClass) {
      // If we have a specific container for the remove button,
      // place it as the last child of that container:
      row.find('[class*="' + options.deleteContainerClass + '"]').append(delButtonHTML);
    } else if (row.is('TR')) {
      // If the forms are laid out in table rows, insert
      // the remove button into the last table cell:
      row.children(':last').append(delButtonHTML);
    } else if (row.is('UL') || row.is('OL')) {
      // If they're laid out as an ordered/unordered list,
      // insert an <li> after the last list item:
      row.append('<li>' + delButtonHTML + '</li>');
    } else {
      // Otherwise, just insert the remove button as the
      // last child element of the form's container:
      row.append(delButtonHTML);
    }

    // Check if we're under the minimum number of forms - not to display delete link at rendering
    if (!showDeleteLinks()) {
      row.find('a.' + delCssSelector).hide();
    }

    row.find('a.' + delCssSelector).click(function() {
      console.log('clicked delete');

      var result = confirm("Are you sure you want to Delete?");
      if (result) {
        // $('.delete-row').on('click',function(){
        console.log("click worked1", this);
        var row = $(this).parents('.dynamic-form');
        console.log('row', row);
        var itemIdInput = row.find('input:hidden[id $= "-id"]');
        console.log('itemIdInput', itemIdInput);
        var itemId = itemIdInput.val();
        console.log('item id', itemId);
        var deleteInput = `<input type="hidden" name="line_items_to_delete" value="${itemId}">`;
        console.log(deleteInput);
        if ($(deleteInput).val()) {
          console.log("Test1");
          $('#line_items_to_delete').append(deleteInput);
        }

        var row = $(this).parents('.' + options.formCssClass),
          // <input type="hidden" name="newcompanycontact_set-1-DELETE" id="id_newcompanycontact_set-1-DELETE">
          del = row.find('input:hidden[id $= "-DELETE"]'),
          //del = row.find('input:checkbox[id $= "-DELETE"]');
          buttonRow = row.siblings("a." + addCssSelector + ', .' + options.formCssClass + '-add'),
          forms;
        if (del.length) {
          // We're dealing with an inline formset.
          // Rather than remove this form from the DOM, we'll mark it as deleted
          // and hide it, then let Django handle the deleting:
          del.val('on');
          row.hide();
          forms = $('.' + options.formCssClass); //.not(':hidden');
          totalForms.val(forms.length);
        } else {
          row.remove();
          // Update the TOTAL_FORMS count:
          forms = $('.' + options.formCssClass).not('.formset-custom-template');
          totalForms.val(forms.length);
        }
        for (var i = 0, formCount = forms.length; i < formCount; i++) {
          // Apply `extraClasses` to form rows so they're nicely alternating:
          applyExtraClasses(forms.eq(i), i);
          if (!del.length) {
            // Also update names and IDs for all child controls (if this isn't
            // a delete-able inline formset) so they remain in sequence:
            forms.eq(i).find(childElementSelector).each(function() {
              updateElementIndex($(this), options.prefix, i);
            });
          }
        }
        // Check if we've reached the minimum number of forms - hide all delete link(s)
        if (!showDeleteLinks()) {
          $('a.' + delCssSelector).each(function() {
            $(this).hide();
          });
        }
        // Check if we need to show the add button:
        if (buttonRow.is(':hidden') && showAddButton()) buttonRow.show();
        // If a post-delete callback was provided, call it with the deleted form:
        if (options.removed) options.removed(row);
        // console.log("hero");
        return false;
      }
    });
  };

$$.each(function(i) {
  var row = $(this),
    del = row.find('input:checkbox[id $= "-DELETE"]');
  if (del.length) {
    // If you specify "can_delete = True" when creating an inline formset,
    // Django adds a checkbox to each form in the formset.
    // Replace the default checkbox with a hidden field:
    if (del.is(':checked')) {
      // If an inline formset containing deleted forms fails validation, make sure
      // we keep the forms hidden (thanks for the bug report and suggested fix Mike)
      del.before('<input type="hidden" name="' + del.attr('name') + '" id="' + del.attr('id') + '" value="on" />');
      row.hide();
    } else {
      del.before('<input type="hidden" name="' + del.attr('name') + '" id="' + del.attr('id') + '" />');
    }
    // Hide any labels associated with the DELETE checkbox:
    $('label[for="' + del.attr('id') + '"]').hide();
    del.remove();
  }
  if (hasChildElements(row)) {
    row.addClass(options.formCssClass);
    if (row.is(':visible')) {
      insertDeleteLink(row);
      applyExtraClasses(row, i);
    }
  }
});

I believe the problem may have something to do with how the delete button is being created...based on recent research but I can't figure out what to change as I'm a newb at Javascript.

Thanks in advance for any thoughts.

Huangism
  • 16,278
  • 7
  • 48
  • 74
Steve Smith
  • 1,019
  • 3
  • 16
  • 38
  • change `$(".delete-row").on('click', function() {` to `$(document).on("click",".delete-row",function(){ //all code here })` – Swati Jun 30 '21 at 14:12
  • @Swati Hello! And thank you and yes I've tried that and it doesn't help. I really think it has something to do with how the link is being created. – Steve Smith Jun 30 '21 at 14:15
  • Did you check if delete button has that class or not and what is `options.deleteCssClass` ? – Swati Jun 30 '21 at 14:18
  • 1
    If the issue is not delegating the click event then you would need to create a simplified example showing the issue – Huangism Jun 30 '21 at 14:18
  • @Swati Yes the link has that class and options.deleteCssClass is a where you set the name of the class. In this case I verified it was delete-row. I've read about how if the link is not created properly and then it is deleted the parent disappears and that's why the subsequent clicks don't work. I think that's kinda what's going on here? – Steve Smith Jun 30 '21 at 14:21
  • 1
    Not sure . But , as Huangism said you should create [mcve] so that we can help you . – Swati Jun 30 '21 at 14:30
  • @Swati Ok....I'll try to reduce the code much further. Thanks as always for taking the time to help. – Steve Smith Jun 30 '21 at 14:32
  • @Swati As I kinda suspected the issue seems to be with the program I'm using...and not as much the onclick event...I have reopened a different issue...trying to narrow down the problem as much as possible. Here is the new issue...https://stackoverflow.com/questions/68199615/what-is-the-difference-between-row-append-and-filter – Steve Smith Jun 30 '21 at 18:03
  • @Swati I am developing using Django. I discovered today a very similar if not identical issue to what I am experiencing regarding formsets and dynamically added forms. This appears to be the crux of my issue. Thank you so much for your input. Here's the issue that is basically identical to mine. https://stackoverflow.com/questions/61036000/how-to-handle-javascript-event-inside-a-inlineformset-factory-with-formset-media – Steve Smith Jul 03 '21 at 02:31

0 Answers0