javascript - 从动态填充表 JavaScript 中的特定行获取特定单元格值

标签 javascript jquery html

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

在格式化我的问题时,我偶然发现了这个完全相同的问题(我搜索了一个小时才决定提问),但它不包含任何对我有用的解决方案: Get Value of HTML cells in row clicked with Javascript

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);
        });
    }

以防万一你需要它,这是我获取 JSON 数据的 ajax 调用:

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)

实际上它看起来像这样: enter image description here

我的问题是,当我按下第一行的编辑按钮时,如何让我的脚本知道按下的是特定行上的编辑按钮,以及我如何才能知道例如 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"                      
        }
    }   
]

最佳答案

由于使用了 jQuery,因此您应该遵循两个未记录的规则:

  1. Do not use id unless required (such as Bootstrap data- attributes), use class. Note: The demo below demonstrates how we can use class exclusively and no longer have any dependency on ids.

  2. Do not use on-event attributes <button onclick="fnc()" >

第一条规则适用于演示,第二条规则不相关,只是为了完整性而添加。此外,ID 必须是唯一的——提供的 OP 代码生成了重复的 button#editBtn .

动态添加的元素无法绑定(bind)到事件,因此任何向编辑/删除按钮添加“点击”事件的尝试都会失败。只有加载时存在的元素才能注册到事件中,因此 <tbody> 中的任何祖先元素至 document可以注册到点击事件,然后事件可以委托(delegate)给编辑/删除按钮。一般而言,委托(delegate)事件涉及用于具体确定哪些元素对事件作出 react 以及哪些元素忽略此类事件的编程模式。

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

$(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>

关于javascript - 从动态填充表 JavaScript 中的特定行获取特定单元格值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55786594/

相关文章:

javascript - 无法在 React 组件中呈现 JSON 数据

jquery - 如何选择具有给定 id 的特定 div 内的表行元素

html - 如何文本对齐 div 内的 svg 元素

javascript - jquery Slidebar 在 IE 中不工作

javascript - 将 knockoutjs 与 KoGrid 一起使用不能在 Chrome 或 FF 中工作,但可以在 IE8 中工作

javascript - 通过表单编辑 CSS - 实时预览

javascript - 两个对象相等

javascript - 隐藏按钮并在单击按钮时显示隐藏的 p-tag

JavaScript/Socket.io Web 应用程序不执行任何 JS 命令

html - 如何使用 Angular 将值绑定(bind)到 Web 组件的属性?