最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to detect button click event inside DataTable child row? - Stack Overflow

programmeradmin1浏览0评论

I have the standard DataTable code which populates the datatable and shows child rows on row clicks. Inside the child row (using the format function) i have added a button and i want to do something when it's clicked but each time i click the button(data table contains child row inside a new tr->td) the event of td click which is used to open/close child rows is fired and i get "Uncaught TypeError: Cannot read property '0' of undefined" for the d[] array in format function.

This is the code for the child rows open/close:

$('tbody').on('click', 'td', function() {
    var tr = $(this).closest('tr');
    id = $(this).closest('table').attr('id');
    table = $('#' + id).DataTable();
    var row = table.row(tr);
    if (row.child.isShown()) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    } else {
        // Open this row
        row.child(format(row.data(), id)).show();
        tr.addClass('shown');
    }
});

function format(d, id) {
// `d` is the original data object for the row
if(sessionStorage['name']!=undefined)
    return '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + "<button class='btn btn-default' id='joinbutton' role='button'>Join Session</button>";
else
return '<div>' + '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + '</div>';

}

Is there a way to either prevent the td click event from being fired for child rows or to detect the button click somehow? Thanks

I have the standard DataTable code which populates the datatable and shows child rows on row clicks. Inside the child row (using the format function) i have added a button and i want to do something when it's clicked but each time i click the button(data table contains child row inside a new tr->td) the event of td click which is used to open/close child rows is fired and i get "Uncaught TypeError: Cannot read property '0' of undefined" for the d[] array in format function.

This is the code for the child rows open/close:

$('tbody').on('click', 'td', function() {
    var tr = $(this).closest('tr');
    id = $(this).closest('table').attr('id');
    table = $('#' + id).DataTable();
    var row = table.row(tr);
    if (row.child.isShown()) {
        // This row is already open - close it
        row.child.hide();
        tr.removeClass('shown');
    } else {
        // Open this row
        row.child(format(row.data(), id)).show();
        tr.addClass('shown');
    }
});

function format(d, id) {
// `d` is the original data object for the row
if(sessionStorage['name']!=undefined)
    return '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + "<button class='btn btn-default' id='joinbutton' role='button'>Join Session</button>";
else
return '<div>' + '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + '</div>';

}

Is there a way to either prevent the td click event from being fired for child rows or to detect the button click somehow? Thanks

Share Improve this question edited Feb 13, 2016 at 12:07 J_P 6411 gold badge8 silver badges24 bronze badges asked Feb 13, 2016 at 11:30 yishaiyishai 931 gold badge3 silver badges15 bronze badges 3
  • 1 you may add the event to your function $('tbody').on('click', 'td', function(e) { so that you may test for e.target element, if it is not the right one you may stop your function, or you may handle the event stoppropagation – gaetanoM Commented Feb 13, 2016 at 11:37
  • Being too plex to make both functions inside the same function i exctracted the button to the table into a td. thanks for the help i may e back to your answer later on – yishai Commented Feb 13, 2016 at 14:23
  • Can you please provide plete example like using JSFiddle, which will be easier to understand the exact problem. Meanwhile you can try adding event.stopPropagation(); inside button click event. – Nitin Garg Commented Feb 13, 2016 at 14:58
Add a ment  | 

3 Answers 3

Reset to default 6

I propose the snippet following my remark (see the ments, not those in the format function, they are required for me to make the snippet running):

function format(d, id) {
  // `d` is the original data object for the row
  //if(sessionStorage['name']!=undefined)
    return '<img src="http://icons.iconarchive./icons/treetog/junior/256/image-format-jpg-icon.png" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + "<button class='btn btn-default' id='joinbutton' role='button'>Join Session</button>";
  //else
    //return '<div>' + '<img src="images/photo.jpg" id="photo" />' + '<p>Session created by:' + d[0] + '</p>' + '<p>Start Date:' + d.start_date + '</p>' + '<p>Extra info:' + d[3] + '</p>' + '</div>';

}

// to handle the joinbutton created dynamically you need:
// avoid to use the same ID for more than one element
$(document).on('click', 'button[role="button"]', function(e) {
  alert('This is the button');
});

$(function () {
  $('tbody').on('click', 'td', function(e) {
    // to avoid to receive the button click inside the td you need:
    if ($(e.target).is(':not(td)')) {
      alert('This is inside td');
      return;
    }
    var tr = $(this).closest('tr');
    id = $(this).closest('table').attr('id');
    table = $('#' + id).DataTable();
    var row = table.row(tr);
    if (row.child.isShown()) {
      // This row is already open - close it
      row.child.hide();
      tr.removeClass('shown');
    } else {
      // Open this row
      row.child(format(row.data(), id)).show();
      tr.addClass('shown');
    }
  });
});
table, th, td {
  border: 1px solid black;
  border-collapse: collapse;
}
th, td {
  padding: 10px;
}
<link href="http://code.jquery./ui/1.11.3/themes/smoothness/jquery-ui.css" rel="stylesheet"/>
<script src="http://code.jquery./jquery-1.11.3.min.js"></script>
<script src="http://code.jquery./ui/1.11.3/jquery-ui.js"></script>

<link href="//cdn.datatables/1.10.11/css/jquery.dataTables.min.css" rel="stylesheet">
<script src="//cdn.datatables/1.10.11/js/jquery.dataTables.min.js"></script>


<table id="tblId">
    <thead>
    <tr>
        <th>Month</th>
        <th>Savings</th>
    </tr>
    </thead>
    <tfoot>
    <tr>
        <td>Sum</td>
        <td>$180</td>
    </tr>
    </tfoot>
    <tbody>
    <tr>
        <td>January</td>
        <td>$100</td>
    </tr>
    <tr>
        <td>February</td>
        <td>$80</td>
    </tr>
    </tbody>
</table>

I resolve my problem with @gaemaf solution:

// Handle click on checkbox
$("#example tbody").on("click", 'input[type="checkbox"]', function(e){
    var $row = $(this).closest("tr");

    if(this.checked){
        $row.addClass("active");
    } else {
        $row.removeClass("active");
    }

    // Prevent click event from propagating to parent
    e.stopPropagation();
});

// Handle click on table cells
$("#example tbody").on("click", "td", function(e){
    // Begin Solution
    if ($(e.target).is(':not(td)')) {
        return;
    }
    // End solution
    $(this).parent().find('input[type="checkbox"]').trigger("click");
});

SOLUTION

Add click handler to the button and return false from the handler to prevent default action and stop the event from propagating to parent element. Alternatively you may call stopPropagation() and preventDefault().

$('#example tbody').on('click', 'button', function (e) {

   // ... skipped ...

   return false;
});

It would be better to remove id='joinbutton' and use class name instead, for example btn-join. Then you would be able to target specific button with the code below.

$('#example tbody').on('click', '.btn-join', function (e) {

   // ... skipped ...

   return false;
});

DEMO

See this jsFiddle for code and demonstration.

发布评论

评论列表(0)

  1. 暂无评论