【问题标题】:How to make HTML table cell editable?如何使 HTML 表格单元格可编辑?
【发布时间】:2011-08-26 03:36:45
【问题描述】:

我想让html表格的一些单元格可编辑,只需双击一个单元格,输入一些文本,更改就可以发送到服务器。我不想使用像 dojo 数据网格这样的工具包。因为它提供了一些其他功能。你能给我一些代码sn-p或如何实现它的建议吗?

【问题讨论】:

    标签: html editor html-table cell


    【解决方案1】:

    您可以在有问题的单元格、行或表格上使用 contenteditable 属性。

    针对 IE8 兼容性进行了更新

    <table>
    <tr><td><div contenteditable>I'm editable</div></td><td><div contenteditable>I'm also editable</div></td></tr>
    <tr><td>I'm not editable</td></tr>
    </table>
    

    请注意,如果您使表格可编辑,至少在 Mozilla 中,您可以删除行等。

    您还需要检查您的目标受众的浏览器是否支持此属性。

    至于监听更改(以便您可以发送到服务器),请参阅contenteditable change events

    【讨论】:

    • 谢谢。 HTML5 似乎支持 contenteditable。我正在寻找一种适用于 html4 的解决方案。
    • 虽然它最终被编入 HTML5 的标准中,但它已经在大多数旧浏览器中得到了很好的支持(FF3 中只有部分支持除外):caniuse.com/contenteditable(虽然不在移动设备中)
    • 很棒的提示。我一直在寻找它。谢谢你。
    • 请向我解释为什么单元格中必须有一个 DIV 才能使其适用于 IE。使用&lt;td contenteditable=true&gt; 不会使单元格在 IE 中可编辑。我认为 contenteditable 适用于 any HTML 元素?
    • 如果您需要 IE8 兼容性,您只需在创建新的&lt;td&gt; 时添加contenteditable div。否则,如帖子中所述,您可以在单元格、行或表格上添加contenteditable
    【解决方案2】:

    如果你使用 Jquery,这个插件可以帮助你 很简单,但是很好

    https://github.com/samuelsantosdev/TableEdit

    【讨论】:

    • 这看起来像一个有趣的插件。如何使用它的文档可以在 index.html 文件中找到。请查看meta.stackexchange.com/questions/8231/…,了解为什么包含更多信息而不是仅提供链接可以得到更好的答案。
    【解决方案3】:

    HTML5 支持 contenteditable,

    <table border="3">
    <thead>
    <tr>Heading 1</tr>
    <tr>Heading 2</tr>
    </thead>
    <tbody>
    <tr>
    <td contenteditable='true'></td>
    <td contenteditable='true'></td>
    </tr>
    <tr>
    <td contenteditable='true'></td>
    <td contenteditable='true'></td>
    </tr>
    </tbody>
    </table>
    

    第三方编辑

    引用mdn entry on contenteditable

    该属性必须采用以下值之一:

    • true或空字符串,表示元素必须是可编辑的;

    • false,表示该元素不可编辑。

    如果没有设置这个属性,它的默认值是继承自它的 父元素。

    此属性是枚举属性,而不是布尔属性。这意味着 明确使用值 true、false 或 empty 之一 string 是强制性的,并且不允许使用简写 ...。

    // wrong not allowed
    <label contenteditable>Example Label</label> 
    
    // correct usage
    <label contenteditable="true">Example Label</label>.
    

    【讨论】:

    • 很奇怪。通常属性值不是true,它是任何名称。例如,&lt;td contenteditable='contenteditable'&gt;&lt;/td&gt;
    • contenteditable 的可能状态:contenteditable**="" or **contenteditable**="true" 表示元素是可编辑的。 **contenteditable**="false" 表示元素不可编辑。 **contenteditable**="inherit" 表示如果其直接父元素是可编辑的,则该元素是可编辑的。这是默认值。当您将 **contenteditable 添加到元素时,浏览器将使该元素可编辑。此外,该元素的任何子元素也将变为可编辑,除非子元素明确 **contenteditable**="false"。
    • 我知道,我只是觉得这很奇怪,因为大多数其他属性都没有这种语法。
    【解决方案4】:

    试试这个代码。

    $(function () {
     $("td").dblclick(function () {
        var OriginalContent = $(this).text();
    
        $(this).addClass("cellEditing");
        $(this).html("<input type="text" value="&quot; + OriginalContent + &quot;" />");
        $(this).children().first().focus();
    
        $(this).children().first().keypress(function (e) {
            if (e.which == 13) {
                var newContent = $(this).val();
                $(this).parent().text(newContent);
                $(this).parent().removeClass("cellEditing");
            }
        });
    
     $(this).children().first().blur(function(){
        $(this).parent().text(OriginalContent);
        $(this).parent().removeClass("cellEditing");
     });
     });
    });
    

    您也可以访问此链接了解更多详情:

    【讨论】:

    【解决方案5】:

    我有三种方法, 在这里,您可以根据需要同时使用&lt;input&gt;&lt;textarea&gt;

    1.在&lt;td&gt; 中使用输入。

    在所有&lt;td&gt;s 中使用&lt;input&gt; 元素,

    <tr><td><input type="text"></td>....</tr>
    

    此外,您可能希望将输入大小调整为其td 的大小。例如,

    input { width:100%; height:100%; }
    

    您还可以在输入框不被编辑时更改它的边框颜色。

    2。使用contenteditable='true' 属性。 (HTML5)

    但是,如果您想使用contenteditable='true',您可能还需要将适当的值保存到数据库中。您可以使用 ajax 来实现。

    您可以将密钥处理程序keyupkeydownkeypress 等附加到&lt;td&gt;。此外,当用户连续键入时,最好将一些 delay() 与这些事件一起使用,ajax 事件不会在用户每次按下时触发。例如,

    $('table td').keyup(function() {
      clearTimeout($.data(this, 'timer'));
      var wait = setTimeout(saveData, 500); // delay after user types
      $(this).data('timer', wait);
    });
    function saveData() {
      // ... ajax ...
    }
    

    3.点击时将&lt;input&gt; 附加到&lt;td&gt;

    &lt;td&gt;被点击时在td中添加输入元素,根据td的值替换其值。当输入模糊时,用输入的值改变`td的值。所有这些都使用 javascript。

    【讨论】:

    • 很遗憾,您错过了问题部分“如何使 HTML 表格单元格可编辑?”特别是在示例 2 中。用户询问如何在双击时实现此目的。你能实现缺少的部分吗?
    • @BhaveshGangani 我对contenteditable=true 有一些问题你能帮我解决这个问题吗?
    • 我当然可以试试。你有 js fiddle 吗?
    【解决方案6】:

    这其实很简单, 这是我的 HTML、jQuery 示例……它就像一个魅力,我使用在线 json 数据示例构建所有代码。 干杯

    >

    <table id="myTable"></table>
    

    >

    <script>
            var url = 'http://jsonplaceholder.typicode.com/posts';
            var currentEditedIndex = -1;
            $(document).ready(function () {
                $.getJSON(url,
                function (json) {
                    var tr;
                    tr = $('<tr/>');
                    tr.append("<td>ID</td>");
                    tr.append("<td>userId</td>");
                    tr.append("<td>title</td>");
                    tr.append("<td>body</td>");
                    tr.append("<td>edit</td>");
                    $('#myTable').append(tr);
    
                    for (var i = 0; i < json.length; i++) {
                        tr = $('<tr/>');
                        tr.append("<td>" + json[i].id + "</td>");
                        tr.append("<td>" + json[i].userId + "</td>");
                        tr.append("<td>" + json[i].title + "</td>");
                        tr.append("<td>" + json[i].body + "</td>");
                        tr.append("<td><input type='button' value='edit' id='edit' onclick='myfunc(" + i + ")' /></td>");
                        $('#myTable').append(tr);
                    }
                });
    
    
            });
    
    
            function myfunc(rowindex) {
    
                rowindex++;
                console.log(currentEditedIndex)
                if (currentEditedIndex != -1) {  //not first time to click
                    cancelClick(rowindex)
                }
                else {
                    cancelClick(currentEditedIndex)
                }
    
                currentEditedIndex = rowindex; //update the global variable to current edit location
    
                //get cells values
                var cell1 = ($("#myTable tr:eq(" + (rowindex) + ") td:eq(0)").text());
                var cell2 = ($("#myTable tr:eq(" + (rowindex) + ") td:eq(1)").text());
                var cell3 = ($("#myTable tr:eq(" + (rowindex) + ") td:eq(2)").text());
                var cell4 = ($("#myTable tr:eq(" + (rowindex) + ") td:eq(3)").text());
    
                //remove text from previous click
    
    
                //add a cancel button
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(4)").append(" <input type='button' onclick='cancelClick("+rowindex+")' id='cancelBtn' value='Cancel'  />");
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(4)").css("width", "200");
    
                //make it a text box
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(0)").html(" <input type='text' id='mycustomid' value='" + cell1 + "' style='width:30px' />");
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(1)").html(" <input type='text' id='mycustomuserId' value='" + cell2 + "' style='width:30px' />");
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(2)").html(" <input type='text' id='mycustomtitle' value='" + cell3 + "' style='width:130px' />");
                $("#myTable tr:eq(" + (rowindex) + ") td:eq(3)").html(" <input type='text' id='mycustomedit' value='" + cell4 + "' style='width:400px' />");
    
            }
    
            //on cancel, remove the controls and remove the cancel btn
            function cancelClick(indx)
            {
    
                //console.log('edit is at row>> rowindex:' + currentEditedIndex);
                indx = currentEditedIndex;
    
                var cell1 = ($("#myTable #mycustomid").val());
                var cell2 = ($("#myTable #mycustomuserId").val());
                var cell3 = ($("#myTable #mycustomtitle").val());
                var cell4 = ($("#myTable #mycustomedit").val()); 
    
                $("#myTable tr:eq(" + (indx) + ") td:eq(0)").html(cell1);
                $("#myTable tr:eq(" + (indx) + ") td:eq(1)").html(cell2);
                $("#myTable tr:eq(" + (indx) + ") td:eq(2)").html(cell3);
                $("#myTable tr:eq(" + (indx) + ") td:eq(3)").html(cell4);
                $("#myTable tr:eq(" + (indx) + ") td:eq(4)").find('#cancelBtn').remove();
            }
    
    
    
        </script>
    

    【讨论】:

      【解决方案7】:

      这是一个可运行的示例。

      $(function(){
        $("td").click(function(event){
          if($(this).children("input").length > 0)
                return false;
      
          var tdObj = $(this);
          var preText = tdObj.html();
          var inputObj = $("<input type='text' />");
          tdObj.html("");
      
          inputObj.width(tdObj.width())
                  .height(tdObj.height())
                  .css({border:"0px",fontSize:"17px"})
                  .val(preText)
                  .appendTo(tdObj)
                  .trigger("focus")
                  .trigger("select");
      
          inputObj.keyup(function(event){
            if(13 == event.which) { // press ENTER-key
              var text = $(this).val();
              tdObj.html(text);
            }
            else if(27 == event.which) {  // press ESC-key
              tdObj.html(preText);
            }
          });
      
          inputObj.click(function(){
            return false;
          });
        });
      });
      <html>
          <head>
              <!-- jQuery source -->
              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
          </head>
          <body>
              <table align="center">
                  <tr> <td>id</td> <td>name</td> </tr>
                  <tr> <td>001</td> <td>dog</td> </tr>
                  <tr> <td>002</td> <td>cat</td> </tr>
                  <tr> <td>003</td> <td>pig</td> </tr>
              </table>
          </body>
      </html>

      【讨论】:

        【解决方案8】:

        您可以使用 x-editable https://vitalets.github.io/x-editable/ 它来自引导程序的很棒的库

        【讨论】:

          【解决方案9】:

          只需在单击单元格时动态插入 &lt;input&gt; 元素到 &lt;td&gt; 中。只有简单的 HTML 和 Javascript。不需要contentEditablejqueryHTML5

          https://Jsfiddle.net/gsivanov/38tLqobw/2/

          【讨论】:

            【解决方案10】:

            这是最重要的一点,尽管您不需要让代码变得如此凌乱。相反,您可以遍历所有 &lt;td&gt; 并添加带有属性的 &lt;input&gt;,最后放入值。

            function edit(el) {
              el.childNodes[0].removeAttribute("disabled");
              el.childNodes[0].focus();
              window.getSelection().removeAllRanges();
            }
            function disable(el) {
              el.setAttribute("disabled","");
            }
            <table border>
            <tr>
            <td ondblclick="edit(this)"><input value="cell1" disabled onblur="disable(this)"></td>
            <td ondblclick="edit(this)"><input value="cell2" disabled onblur="disable(this)"></td>
            <td ondblclick="edit(this)"><input value="cell3" disabled onblur="disable(this)"></td>
            <td ondblclick="edit(this)"><input value="so forth..." disabled onblur="disable(this)">
            </td>
            </tr>
            </table>

            【讨论】:

              【解决方案11】:

              我将其用于可编辑字段

              <table class="table table-bordered table-responsive-md table-striped text-center">
                <thead>
                  <tr>
                    <th class="text-center">Citation</th>
                    <th class="text-center">Security</th>
                    <th class="text-center">Implementation</th>
                    <th class="text-center">Description</th>
                    <th class="text-center">Solution</th>
                    <th class="text-center">Remove</th>
                  </tr>
                </thead>
                <tbody>
                  <tr>
                    <td class="pt-3-half" contenteditable="false">Aurelia Vega</td>
                    <td class="pt-3-half" contenteditable="false">30</td>
                    <td class="pt-3-half" contenteditable="false">Deepends</td>
                    <td class="pt-3-half" contenteditable="true"><input type="text" name="add1" value="spain" class="border-none"></td>
                    <td class="pt-3-half" contenteditable="true"><input type="text" name="add1" value="marid" class="border-none"></td>
                    <td>
                      <span class="table-remove"><button type="button"
                                            class="btn btn-danger btn-rounded btn-sm my-0">Remove</button></span>
                    </td>
                  </tr>
                </tbody>
              </table>

              【讨论】:

                【解决方案12】:

                点击时将&lt;input&gt; 添加到&lt;td&gt;。 模糊时将&lt;input&gt;更改为&lt;span&gt;

                【讨论】:

                  【解决方案13】:

                  如果你的表格有很多功能(排序、导出、更新、编辑等),

                  我会推荐引导表。

                  关于编辑实践:

                  监听事件:click-cell.bs.table 然后在点击后立即将属性 contenteditable 添加到 td

                  您可能不想在每一列中都允许编辑,所以我自己用 JS 添加了data-editable 属性来确定这一点。

                  演示

                  Title 的列允许您编辑

                  <!DOCTYPE html>
                  <html>
                  <head>
                    <!-- jquery -->
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js" integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ==" crossorigin="anonymous"></script>
                  
                    <!-- bootstrap -->
                    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous">
                    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/js/bootstrap.bundle.min.js" integrity="sha384-JEW9xMcG8R+pH31jmWH6WWP0WintQrMb4s7ZOdauHnUtxwoG2vI5DkLtS3qm9Ekf" crossorigin="anonymous"></script>
                  
                    <!-- bootstrap-table-->
                    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.3/bootstrap-table.min.css" integrity="sha512-5RNDl2gYvm6wpoVAU4J2+cMGZQeE2o4/AksK/bi355p/C31aRibC93EYxXczXq3ja2PJj60uifzcocu2Ca2FBg==" crossorigin="anonymous" />
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.3/bootstrap-table.min.js" integrity="sha512-Wm00XTqNHcGqQgiDlZVpK4QIhO2MmMJfzNJfh8wwbBC9BR0FtdJwPqDhEYy8jCfKEhWWZe/LDB6FwY7YE9QhMg==" crossorigin="anonymous"></script>
                  
                    <!--bootstrap-table-lanuage-->
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.3/bootstrap-table-locale-all.min.js" integrity="sha512-1PCRWIvrSQaZjCRWaa0GHWKr1jQA8u79VnIvkAme6BKeoNWe5N89peawTXdVp+kukb8rzNsEY89ocMJqVivdSA==" crossorigin="anonymous"></script>
                    <!--bootstrap-table-export-->
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.3/extensions/export/bootstrap-table-export.min.js" integrity="sha512-cAMZL39BuY4jWHUkLWRS+TlHzd/riowdz6RNNVI6CdKRQw1p1rDn8n34lu6pricfL0i8YXeWQIDF5Xa/HBVLRg==" crossorigin="anonymous"></script>
                  
                    <!-- screenshots -->
                    <script src="https://cdn.jsdelivr.net/npm/es6-promise@4.2.8/dist/es6-promise.auto.min.js" integrity="sha256-Xxrdry6fWSKu1j2ALyuK/gHFQ+2Bp76ZrR6f3QXI47Y=" crossorigin="anonymous"></script>
                    <script src="https://cdn.jsdelivr.net/npm/html2canvas@1.0.0-rc.7/dist/html2canvas.min.js" integrity="sha256-Ax1aqtvxWBY0xWND+tPZVva/VQZy9t1Ce17ZJO+NTRc=" crossorigin="anonymous"></script>
                  
                  
                    <!-- tableexport.jquery.plugin If you want to export, then you must add it. -->
                    <script src="https://cdn.jsdelivr.net/npm/tableexport.jquery.plugin@1.10.22/tableExport.min.js" integrity="sha256-Dsris8trQzzQXIM6PgMzSugaNyUacxaR9o2VrJalh6Y=" crossorigin="anonymous"></script>
                  
                    <!-- font-awesome -->
                    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" />
                    <script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/js/all.min.js" integrity="sha512-RXf+QSDCUQs5uwRKaDoXt55jygZZm2V++WUZduaU/Ui/9EGp3f/2KZVahFZBKGH0s774sd3HmrhUy+SgOFQLVQ==" crossorigin="anonymous"></script>
                  
                    <style>
                      html {
                        font-family: sans-serif;
                        line-height: 1.15;
                        -webkit-text-size-adjust: 100%;
                        -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
                      }
                  
                      h1, h2, h3, h4, h5, h6 {
                        margin-top: 0;
                        margin-bottom: 0.5rem;
                        color: #004a88;
                        text-align: center;
                      }
                  
                      .table-blue {
                        font-family: Arial, Helvetica, sans-serif;
                        border-collapse: collapse;
                        width: 100%;
                      }
                  
                      .table-blue td, .table-blue th {
                        border: 1px solid #ddd;
                        padding: 8px;
                      }
                  
                      .table-blue tr:hover {background-color: #ddd;}
                  
                      .table-blue th {
                        background-color: #004a88;
                        font-size: larger;
                        font-weight: bold;
                        padding-top: 5px;
                        padding-bottom: 5px;
                        text-align: left;
                        color: white;
                      }
                  
                      /* https://stackoverflow.com/a/63412885 */
                      thead, tbody tr {
                        display: table;
                        width: 100%;
                        table-layout: fixed;
                      }
                      tbody {
                        display: block;
                        overflow-y: auto;
                        table-layout: fixed;
                        max-height: 512px;
                      }
                  
                      td {
                        word-break: break-all;
                      }
                  
                    </style>
                  </head>
                  
                  <body>
                  <!-- Table-options:
                  - https://bootstrap-table.com/docs/api/table-options/
                  - https://bootstrap-table.com/docs/extensions/export/
                  -->
                  <table id="myTable" class="table table-striped table-blue"
                         data-toggle="table"
                         data-search="true"
                         data-search-highlight="true"
                         data-show-refresh="true"
                         data-show-toggle="true"
                         data-show-columns="true"
                         data-show-export="true"
                         data-minimum-count-columns="2"
                         data-show-pagination-switch="true"
                         data-pagination="true"
                         data-id-field="id"
                         data-page-list="[10, 25, 50, 100, ALL]"
                         data-show-footer="false"
                         data-side-pagination="client"
                         data-export-types='["csv", "json", "excel", "doc", "sql", "png"]'
                         data-editable = '[false, true, false, false]'
                         data-export-options='{
                          "fileName": "products"
                          }'
                         data-url="https://jsonplaceholder.typicode.com/photos">
                    <thead>
                    <tr>
                      <th data-sortable="true" data-field="id">Id</th>
                      <th data-sortable="true" data-field="title">Title</th>
                      <th data-sortable="true" data-field="url">URL</th>
                      <th data-sortable="true" data-formatter="imageFormatter" data-field="thumbnailUrl">Thumbnail URL</th>
                    </tr>
                    </thead>
                  </table>
                  </body>
                  
                  <script>
                    const TABLE_ID = "myTable";
                    const TABLE = document.getElementById(TABLE_ID)
                  
                    window.onload = () => {
                      const table = $(`#${TABLE_ID}`)
                  
                      function imageFormatter(value, row) {
                        return `<img src="${value}"  style="width:60px;height:60px" loading="lazy"/>`;
                      }
                  
                      function saveData(tdData) {
                        // ... ajax ...
                        console.log("save")
                      }
                  
                      const infoEditable = JSON.parse(TABLE.getAttribute("data-editable"))
                      if (infoEditable === null) {
                        return
                      }
                      table.on('click-cell.bs.table', function (event, field, value, row, td) {
                        td = td[0]
                        if (td.getAttribute("contentEditable")) {
                          return
                        }
                        const index = Array.prototype.indexOf.call(td.parentNode.children, td)
                        if (infoEditable[index]) {
                          td.contentEditable = "true"
                        }
                  
                        td.addEventListener("keyup", (event) => {
                          clearTimeout($.data(this, 'timer'));
                          const wait = setTimeout(saveData, 1000); // delay after user types
                          $(this).data('timer', wait);
                        })
                      })
                    }
                  </script>
                  </html>

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2013-08-24
                    • 2017-07-16
                    • 1970-01-01
                    • 2013-12-18
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多