0

i am trying to use the dynamic table at

https://codepen.io/ashblue/pen/mCtuA

I want to have a button that deletes all rows from the table. SO basically, fire the click function on all instances of the class .table-remove

i tried to do the following

function deleteAll() {

        jQuery('.table-remove').each(function() {
            var currentElement = $(this);
            console.log(currentElement);
            currentElement.trigger('click');
        });
    }

where the click is defined as

$('.table-remove').click(function() {
            console.log("triggered");
            $(this).parents('tr').detach();
        });

but nothing happens when i call the deleteAll function. i dont even se anything on the console

am i doing this right?

AbtPst
  • 6,676
  • 13
  • 69
  • 138
  • 2
    Possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Erik Philips May 05 '17 at 21:56
  • 1
    Maybe ^^. need more evidence though before i use my hammer. – Kevin B May 05 '17 at 21:59
  • 1
    I think this link will help you: https://learn.jquery.com/events/event-delegation/ – myfunkyside May 05 '17 at 21:59
  • 1
    Does clicking the table remove buttons with your mouse work? – Kevin B May 05 '17 at 22:00
  • 1
    wait... you should at least be seeing some logs, if not then this isn't a duplicate of that question, instead your selector is wrong or you are calling deleteAll too soon. – Kevin B May 05 '17 at 22:01
  • 1
    AbtPst, as advised above, delegation of click handling to the table will solve your problem. In addition, the javascript will simplify in several respects if you organize the table rows into a `` and two ``s. – Roamer-1888 May 06 '17 at 00:24
  • 1
    Try [this](https://codepen.io/anon/pen/xdPwZR). – Roamer-1888 May 06 '17 at 11:49
  • thanks @Roamer ! that is perfect. please post it as an answer – AbtPst May 08 '17 at 13:00

2 Answers2

1

If the goal is just to remove the rows, you can do that directly without triggering each individual click event:

function deleteAll() {
  $('.table-remove').closest('tr').remove()
}

If you really need to trigger the click event on each '.table-remove' element, you would do that like so:

function deleteAll() {
  $('.table-remove').each(function() {
    $(this).trigger('click')
  });
}

(...which is roughly equivalent to your existing code. I'm not sure why your existing code isn't working for you; perhaps it's down to your use of jQuery() instead of the $() alias, or you're just not calling the deleteAll() function successfully?)

Daniel Beck
  • 16,972
  • 5
  • 29
  • 49
  • yeah, but, if his current code isn't logging anything... this might not work either. His current code should at the least be logging each .table-remove element. – Kevin B May 05 '17 at 22:03
  • Yes, and if you replace your code with his, it also removes the rows. so where's the problem? – Kevin B May 05 '17 at 22:05
  • Fair enough. Clarification added to answer; if it turns out I'm on the wrong track altogether I'll delete. – Daniel Beck May 05 '17 at 22:15
1

I want to have a button that deletes all rows from the table. So basically, fire the click function on all instances of the class .table-remove.

You could do it that way but it's far simpler to organise your table into :

  • a <thead> containing the header row
  • a <tbody> containing the visible row(s)
  • a <tbody> containing the row template

Thus, the code behind the "Delete All" button can very simply select all rows in the first <tbody> and .remove() them.

HTML

<div class="container">
  <h1>HTML5 Editable Table</h1>
  <p>Through the powers of <strong>contenteditable</strong> and some simple jQuery you can easily create a custom editable table. No need for a robust JavaScript library anymore these days.</p>

  <ul>
    <li>An editable table that exports a hash array. Dynamically compiles rows from headers</li> 
    <li>Simple / powerful features such as add row, remove row, move row up/down.</li>
  </ul>

  <div id="table" class="table-editable">
    <span class="table-add glyphicon glyphicon-plus"></span>
    <table class="table">
      <thead> <!-- <<<< wrap the header row in <thead>...</thead> -->
      <tr>
        <th>Name</th>
        <th>Value</th>
        <th></th>
        <th></th>
      </tr>
      </thead>
      <tbody class="main"> <!-- <<<< wrap the visible row(s) in <tbody>...</tbody> -->
      <tr>
        <td contenteditable="true">Stir Fry</td>
        <td contenteditable="true">stir-fry</td>
        <td>
          <span class="table-remove glyphicon glyphicon-remove"></span>
        </td>
        <td>
          <span class="table-up glyphicon glyphicon-arrow-up"></span>
          <span class="table-down glyphicon glyphicon-arrow-down"></span>
        </td>
      </tr>
      </tbody>
      <tbody class="hide"> <!-- <<<< wrap the template row in its own hidden <tbody>...</tbody> -->
      <tr>
        <td contenteditable="true">Untitled</td>
        <td contenteditable="true">undefined</td>
        <td>
          <span class="table-remove glyphicon glyphicon-remove"></span>
        </td>
        <td>
          <span class="table-up glyphicon glyphicon-arrow-up"></span>
          <span class="table-down glyphicon glyphicon-arrow-down"></span>
        </td>
      </tr>
      </tbody>
    </table>
  </div>

  <button id="export-btn" class="btn btn-primary">Export Data</button>
  <button id="deleteAll-btn" class="btn btn-primary">Delete All</button>
  <p id="export"></p>
</div>

Another aspect is how best to attach click handlers to the three row actions - delete, move-up and move-down.

As the rows are created/appended dynamically, the way to go is to delegate click handling to a container (eg the table) using jQuery's $(static-container).on(event, descendent-selector, handler). This will attach the desired actions to all current rows, and future rows just by appending them.

Javascript

jQuery(function($) {
    var $TABLE = $('#table table');
    var $BTN = $('#export-btn');
    var $BTN2 = $('#deleteAll-btn');
    var $EXPORT = $('#export');
    $('.table-add').on('click', function() {
        $('tbody.hide tr', $TABLE).clone(true).appendTo($('tbody.main', $TABLE));
    });
    $TABLE.on('click', '.table-remove', function() { // delegate row removal to the table
        $(this).closest('tr').remove();
    });
    $TABLE.on('click', '.table-up', function() { // delegate row-up movement to the table
        var $row = $(this).closest('tr');
        $row.insertBefore($row.prev());
    });
    $TABLE.on('click', '.table-down', function() { // delegate row-down movement to the table
        var $row = $(this).closest('tr');
        $row.insertAfter($row.next());
    });
    $BTN.on('click', function() {
        var $headers = $('thead th', $TABLE).not(':empty').map(function() {
            return $(this).text().toLowerCase();
        });
        var $data = $('tbody.main tr', $TABLE).map(function() {
            var $td = $(this).find('td'),
                h = {};
            $headers.each(function(i, header) {
                h[header] = $td.eq(i).text();
            });
            return h;
        });
        $EXPORT.text(JSON.stringify($headers.get().concat($data.get())));
    });
    $BTN2.on('click', function deleteAll() {
        $("tbody.main tr", $TABLE).remove();
    });
});

DEMO.

Roamer-1888
  • 18,384
  • 5
  • 29
  • 42