Si votre tableau a de nombreuses fonctions (tri, exportation, mise à jour, édition, etc.),
Je recommande le tableau bootstrap.
Sur les pratiques d'édition :
Écoutez les événements : cliquer-cellule.bs.table puis ajoute l'attribut contentable au td dès qu'il est cliqué
Il se peut que vous ne souhaitiez pas autoriser l'édition dans chaque colonne, c'est pourquoi j'ai ajouté l'option data-editable
m'attribuer avec JS pour déterminer cela.
Démo
colonne de Title
vous permet de modifier
<!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>