从动态填充的表格JavaScript

时间:2019-04-21 20:42:50

标签: javascript jquery html

我的Web应用程序从JSON对象获取值,并使用其值以及每行上的编辑和删除按钮填充表。我希望我的脚本能够知道按下了哪些行编辑按钮以及该行的单元格值。

在格式化我的问题时,我偶然发现了这个问题(决定问了一个小时,然后才决定问这个问题),但是它没有任何适合我的解决方案: {{3} }

HTML:

<div class="container">     
    <h4>Persons</h4>
    <div class="table-responsive">
        <table class="table table-striped" id="persons_table">
            <thead class="thead-dark">
                <tr>
                    <th scope="col">ID</th>
                    <th scope="col">Name</th>
                    <th scope="col">Email</th>
                    <th scope="col">Phone</th>
                    <th scope="col">Edit</th>
                    <th scope="col">Delete</th>
                </tr>
            </thead>
            <tbody>
                    //dynamically generated rows goes here
            </tbody>
        </table>
    </div>
    <button class="btn btn-sm btn-primary" id="addBtn">New person</button>
</div>

用于填充表格的功能:

function handlePersons(data){ //data is a response from an API (JSON)
    var table = document.getElementById('persons_table');
    data.forEach(function(object) {
        var tr = document.createElement('tr');
        tr.innerHTML = 
        '<td>' + object.ID + '</td>' +
        '<td>' + object.Info.Name + '</td>' +
        '<td>' + object.Info.Email + '</td>' +
        '<td>' + object.Info.PhoneNumber + '</td>' +
        '<td><p data-placement="top" data-toggle="tooltip" title="Edit">
        <button class="btn btn-primary btn-xs" id="editBtn" data-title="Edit" data-toggle="modal" data-target="#edit">
        <span class="fa fa-pencil"></span></button></p></td>' +
        '<td><p data-placement="top" data-toggle="tooltip" title="Delete">
        <button class="btn btn-danger btn-xs" data-title="Delete" data-toggle="modal" data-target="#delete">
        <span class="fa fa-trash"></span></button></p></td>';
        table.appendChild(tr);
        });
    }

只要您需要它,这就是我的ajax调用以获取JSON数据:

function getPersons(){
    var settings = {
            "async" : true,
            "crossDomain" : true,
            "url" : "...",
            "method" : "GET",
            "headers" : {
                "Content-Type" : "application/json",
                "Authorization": "...",
                "cache-control" : "no-cache"
            },
            "processData" : false,
            "data" : ""
        }
        return $.ajax(settings);
}

函数调用:

getPersons().done(handlePersons)

在实践中,它看起来像这样: Get Value of HTML cells in row clicked with Javascript

我的问题是,当我按下第一行上的“编辑”按钮时,如何让我的脚本知道它是被按下的特定行上的“编辑”按钮,以及如何例如用console.log记录该行的名称(约翰)? 这是我尝试过的:

$('#editBtn').on('click', () => {

    var par = $(this).parent().parent(); //to choose table row, also tried one 
                                         //and three .parent() because I don't 
                                         //quite understand this

    var namevalue = par.children("td:nth-child(2)").val(); //also tried with .text()
    console.log(namevalue); //.val = undefined and .text = empty string

});
$('#editBtn').on('click', () => { //also tried with onclick="function" 
                                  //on the button instead of
                                  //jQuery just in case

    var tr = $(this).closest('tr')
    var tdID = $(tr).find('td').eq(0).text();
    var tdName = $(tr).find('td').eq(1).text();
    var tdEmail = $(tr).find('td').eq(2).text();
    var tdPhone = $(tr).find('td').eq(3).text();

    console.log(tdName); //.text logs empty string, .val logs undefined again

});
来自@Cyber​​netic的

JSON数据。对此进行了一点编辑以不泄露任何敏感信息,但仍应在我的代码中产生相同的结果。

[
    {
        "CustomValues": {},
        "Comment": "Here is John",
        "Deleted": false,
        "ID": 1,
        "InfoID": 4,
        "Role": null,
        "StatusCode": null,
        "UpdatedAt": null,
        "UpdatedBy": null,
        "Info": {            
            "DefaultEmailID": 1,
            "DefaultPhoneID": 2,
            "Deleted": false,
            "ID": 3,
            "Name": "John",
            "PhoneNumber": "123-123-123",
            "Email": "john@mail.com"                      
        }
    },
    {
        "CustomValues": {},
        "Comment": "Here is Mike",
        "Deleted": false,
        "ID": 2,
        "InfoID": 6,
        "Role": null,
        "StatusCode": null,
        "UpdatedAt": null,
        "UpdatedBy": null,
        "Info": {            
            "DefaultEmailID": 3,
            "DefaultPhoneID": 4,
            "Deleted": false,
            "ID": 6,
            "Name": "Mike",
            "PhoneNumber": "321-321-321",
            "Email": "mike@mail.com"                      
        }
    }   
]

3 个答案:

答案 0 :(得分:1)

首先,将相同的ID #editBtn赋予多个元素。这是不正确的,在HTML文档的范围内,id必须是唯一的。

第二,我假设您仅将editBtn的click事件放置在页面加载上。但是,由于您是使用AJAX生成这些元素的,因此click事件不会绑定到它们。您需要在AJAX数据成功/完成时调用$('#editBtn')。on('click',function())事件。

第三,这:

var par = $(this).parent().parent();

不起作用。 editBtn在p内,因此$('#editBtn')。parent()。parent()是td,而不是tr。尽管尝试检索数据,但是您需要再添加一个父对象,以这种方式遍历DOM是一种不好的做法,并且可能导致代码破坏和维护难度更大。最好使用特定的ID或数据属性。

答案 1 :(得分:1)

感谢您的数据。

只需将数据添加到每个动态生成的行(tr元素):

function handlePersons(data){ 
    var table = document.getElementById('persons_table');
    data.forEach(function(object) {
        var tr = document.createElement('tr');
        tr.setAttribute('data-id', object.ID) // adding data
        tr.setAttribute('data-name', object.Info.Name) // adding data
        tr.setAttribute('data-email', object.Info.Email) // adding data
        tr.setAttribute('data-phone', object.Info.PhoneNumber) // adding data
        tr.innerHTML = 
        '<td>' + object.ID + '</td>' +
        '<td>' + object.Info.Name + '</td>' +
        '<td>' + object.Info.Email + '</td>' +
        '<td>' + object.Info.PhoneNumber + '</td>' +
        `<td><p data-placement="top" data-toggle="tooltip" title="Edit">
        <button class="btn btn-primary btn-xs" id="editBtn" data-title="Edit" data-toggle="modal" data-target="#edit">
        <span class="fa fa-pencil"></span></button></p></td>' +
        '<td><p data-placement="top" data-toggle="tooltip" title="Delete">
        <button class="btn btn-danger btn-xs" data-title="Delete" data-toggle="modal" data-target="#delete">
        <span class="fa fa-trash"></span></button></p></td>`;
        table.appendChild(tr);
        });
    }

...然后使用表格中编辑按钮的位置来找到其父行并根据需要读取其数据

$('.btn-xs').click(function() {
    $(this).parents('tr').css('background', 'pink')
    id = $(this).parents('tr').data('id')
    name = $(this).parents('tr').data('name')
    email = $(this).parents('tr').data('email')
    phone = $(this).parents('tr').data('phone')
    alert(id + '\n' + name + '\n' + email + '\n' + phone)
})

结果

enter image description here

这里是Fiddle

答案 2 :(得分:1)

由于使用了jQuery,因此应遵循两个未公开的规则:

  
      
  1. 除非必要,否则不要使用id(例如Bootstrap data-属性),请使用类。注意:下面的演示演示了如何独占使用类,而不再依赖于id。

  2.   
  3. 请勿使用事件属性<button onclick =“ fnc()” >

  4.   

第一个规则应用于演示,第二个规则与完整性无关,只是添加了该规则。另外,id必须是唯一的-提供的OP代码正在生成重复的button#editBtn

动态添加的元素不能绑定到事件,因此任何将'click'事件添加到编辑/删除按钮的尝试都将失败。只有在加载时存在的元素才能注册到事件中,因此可以将<tbody>document中的任何祖先元素注册到click事件中,然后可以将该事件委托给“编辑/删除”按钮。一般而言,委派事件涉及一种编程模式,用于专门确定哪些元素对事件做出反应以及哪些元素忽略此类事件。

jQuery事件方法通过提供名为.on()的第一个参数(对eventData来说是第二个)使事件委托变得容易。 eventData是选择符字符串格式的可选参数(与$( ... )中的常用参数相同)。这将成为函数的上下文– $(this)$(event.target) –本质上是单击的按钮。
祖先 eventData
⇩p

$(document).on('click', '.edit', function(e) {...

演示中评论的详细信息

/* 
A: jQuery .append() is not destructive like .innerHTML
   Template literal is easier and cleaner than literal   
   strings.
*/
function handleContacts(data) {
  data.forEach(function(object) {
    $('.contacts').append(`<tr> 
      <td class='content'>${object.ID}</td>
       <td class='content'>${object.Info.Name}</td>
       <td class='content'>${object.Info.Email}</td>
       <td class='content'>${object.Info.PhoneNumber}</td>
       <td><button class="btn btn-primary btn-xs edit"><i class="fas fa-pen"></i></button></p></td>
       <td><button class="btn btn-danger btn-xs delete"><i class="fas fa-trash"></i></button></td></tr>`); //A
  });
}

var data = [{
    "CustomValues": {},
    "Comment": "Here is John",
    "Deleted": false,
    "ID": 1,
    "InfoID": 4,
    "Role": null,
    "StatusCode": null,
    "UpdatedAt": null,
    "UpdatedBy": null,
    "Info": {
      "DefaultEmailID": 1,
      "DefaultPhoneID": 2,
      "Deleted": false,
      "ID": 3,
      "Name": "John",
      "PhoneNumber": "123-123-1231",
      "Email": "john@mail.com"
    }
  },
  {
    "CustomValues": {},
    "Comment": "Here is Mike",
    "Deleted": false,
    "ID": 2,
    "InfoID": 6,
    "Role": null,
    "StatusCode": null,
    "UpdatedAt": null,
    "UpdatedBy": null,
    "Info": {
      "DefaultEmailID": 3,
      "DefaultPhoneID": 4,
      "Deleted": false,
      "ID": 6,
      "Name": "Mike",
      "PhoneNumber": "321-321-3213",
      "Email": "mike@mail.com"
    }
  }
];

// button.add is clicked -- handleContacts() is called
$('.add').on('click', function(e) {
  handleContacts(data);
});

/*
Delegate click event to document
$(this) or $(e.target) is button.delete
Get the .closest() <tr> and remove() it.
*/
$(document).on('click', '.delete', function(e) {
  $(e.target).closest('tr').remove();
});

/*
Delegate click event to document
Note: Any dynamically added elements cannot be bound to 
      events. Events must be bound to an element that 
      existed at load time.
$(this) or $(e.target) is button.edit
*/
/*
B: Get the .closest() <tr>
C: In this <tr> find() .each() td.content and toggle the
   [contenteditable] attribute true/false
D: In this <tr> find() td[contenteditable] and .focus() on
   the first one .eq(0). Note: $(this)[0] is a dereferenced
   "this" because jQuery will not recognize the JavaScript
   method .toggleAttribute()
*/
$(document).on('click', '.edit', function(e) {
  var row = $(e.target).closest('tr'); //B
  row.find('.content').each(function() {
    $(this)[0].toggleAttribute('contenteditable');
  }); //C
  row.find('[contenteditable]').eq(0).focus(); //D
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
<link href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" rel="stylesheet" crossorigin="anonymous">

<div class="container">
  <div class="table-responsive">
    <table class="table table-striped contacts">
      <caption style='caption-side:top'><h4>Contacts</h4></caption>
      <thead class="thead-dark">
        <tr>
          <th scope="col">ID</th>
          <th scope="col">Name</th>
          <th scope="col">Email</th>
          <th scope="col">Phone</th>
          <th scope="col">Edit</th>
          <th scope="col">Delete</th>
        </tr>
      </thead>
      <tbody>

      </tbody>
    </table>
  </div>
  <button class="btn btn-sm btn-primary add">Add Contacts</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.3.1/js/bootstrap.min.js"></script>