繁体   English   中英

可编辑的表格单元格html

[英]editable table cells html

我正在用 html 制作一个表格,该表格使用 javascript 添加新行,具有可编辑的单元格,然后允许用户单击保存并保存对单元格的编辑。 但是,我编写的代码仅在添加的第一行中有效并执行此操作。 当我尝试添加新行时,我的 save() 函数不再起作用。 我知道这是因为我正在使用 id 访问表格单元格,因此多个元素具有相同的 id,但我不知道如何修复它。

<table id="myTable"> 
<tr>
<th>1</th>
<th>2</th>
</tr>
</table>
<button onclick="addRow()">Add row button</button>
<script>
function addRow() {

  let tableRef = document.getElementById('myTable');

  let newRow = tableRef.insertRow(-1);

  let firstcell = newRow.insertCell(0);

  firstcell.setAttribute("id","firstcell")

  let secondcell = newRow.insertCell(1);
  secondcell.setAttribute("id","secondcell")

  var input1=document.createElement('input')

  secondcell.appendChild(input1);

  var btn = document.createElement('button');

btn.type = "button";

btn.className = "save";

let btntext= document.createTextNode("save button");

btn.appendChild(btntext)

btn.setAttribute("onclick","save()")

firstcell.appendChild(btn);

}



function save(){

  input1rref=document.getElementById("input1")

  input1value=input1rref.value

  input1text=document.createTextNode(input1value);

  x=document.getElementById("secondcell")

  x.replaceChild(input1text,input1rref)
}
</script>
<style>
  table{
    padding:10px;
    border: 2px solid black;

  }
  button{
    padding:10px 20px;
  }
</style>

原因是您为多行中的控件分配了相同的 ID(当用户添加行时)。

你应该做什么:

  1. 跟踪行数并将行号附加到所有 setAttribute("id"... 行中的控件。示例:
superassetCell.setAttribute("id", "benchmarkcell");

// should be 
superassetCell.setAttribute("id", "benchmarkcell" + row_number);

getElementById 根据定义对具有唯一 ID 的元素起作用。

  1. 调用 save 方法时,每一行都应将行号作为参数传递给 save。

签出这个问题

如果您有多个表单控件(例如<input><select><button>等),请将所有内容包装在<form>中。 使用.classtagNamename[attribute]来引用元素。 正如您在下面的示例中所见, id 仅用于一次引用<form> ,但即使这样也可以很容易地通过name引用。

图 I - HTML 布局

<form id='formID' name='formName'>
  <input id='inputID' name='formControl' type='number'>
  <button name='formControl' type='button'>GO!</button>
  <table class='tableClass'>
    <tr><td></td><td></td></tr>
  </table>
  <select name='formControl'>
    <option value='1'>I</option>
    <option value='2'>II</option>
    <option value='3'>III</option>
    <option value='4'>IV</option>
  </select>
  <output name='outputName'></output>
</form>

图二- 参考元素

// Reference with .querySelector() to get the first element match
// "." prefix for class
const table = document.querySelector('.tableClass'); 
// "#" prefix for id
const form = document.querySelector('#formID');
// "[]" wrap for other attributes
const input = document.querySelector('[name="formControl"]');
// No prefix or wrap for tagName
const button = document.querySelector('button');
// Use .querySelectorAll() to gather all matches into a NodeList
const options = document.querySelectorAll('option')
// Reference the third <option>
const third = options[2]
// HTMLFormElement Interface
const form = document.forms.formID;
const formALT1 = document.forms.formName;
const formALT2= document.forms['formName'];
const formALT3 = document.forms[0];
// References all form controls under <form>
const fc = form.elements
// Reference form controls id, name, or index notation
const input = fc.inputID;
const output = fc.outputName;
const select = fc[2];
// HTMLFormControlsCollection Interface
// Group all form controls that share the same name
const allFCNames = fc.formControl

阅读以下

活动

事件委托

内联事件处理程序是垃圾

HTMLForm元素

HTMLFormControlsCollection

表单控件

细节在例子中注释

 /** * @desc Utility function that will append a given htmlString into * a given element and renders it into HTML. * @param {string|object} selector - If passed as a string it will * find element by CSS selector. If passed as a variable, it * will reference a DOM Object. This is the object to append * HTML to. * @param {string} htmlString - A string that resembles HTML layout */ function setHTML(selector, htmlString) { const node = typeof selector === 'string' ? document.querySelector(selector) : selector; node.insertAdjacentHTML('beforeend', htmlString); } // Reference the <form> const tForm = document.forms.interface; // Bind the click event to <form> tForm.onclick = action; // Bind the change event to <form> tForm.onchange = format; // Event handler passes Event Object by default function action(e) { // e.target is the <button> the user clicked // The click event is delegated to the <button> clicked by className switch (e.target.className) { case 'add': addRow(e); break; case 'delete': deleteRow(e); break; case 'edit': case 'edit open': editRow(e); break; default: break; } } function addRow(e) { // Reference <tbody> const tData = document.querySelector('.data'); // Reference <thead> const tHead = tData.parentElement.createTHead(); // Get the number of columns let cQty = tHead.rows[0].cells.length; // Define the value/text of each <option> in an array const opts = ["Select Benchmark", "Cash", "Munis", "Bonds", "Stocks", "Commods", "Alts"]; // Reference inserted <tr> let tRow = tData.insertRow(); // Iterate >cQty< times for (let i = 0; i < cQty; i++) { // Reference inserted <td> let tCel = tRow.insertCell(); /* Determine which is the current <td> by (i)ndex Each case creates a <td> and it's content Some elements have too many attributes so using .setAttribute() would bloat the code signifigantly. In those cases render the HTML instead (case 1, case 2, and case 4) */ switch (i) { case 0: const sel = document.createElement('select'); sel.name = 'benchmark'; opts.forEach(o => { let opt = new Option(o, o); sel.add(opt); }); tCel.append(sel); break; case 1: const tilt = `<input name='tilt' class='open' type='number' min='0' step='.01' placeholder='0.00'>`; setHTML(tCel, tilt); break; case 2: const comment = `<input name='comment' class='open' type='text' placeholder='Enter comment'>`; setHTML(tCel, comment); break; case 3: const log = document.createElement('time'); log.textContent = new Date().toLocaleString(); log.className = 'log'; tCel.append(log); break; case 4: const buttons = ` <button name='btn' class='delete' type='button' title='Delete Row'>➖</button> <button name='btn' class='edit open' type='button' title='Edit Row'>✏️</button>`; setHTML(tCel, buttons); break; default: break; } } } // Here we simply find the closest <tr> and remove it function deleteRow(e) { e.target.closest('tr').remove(); } // This function just toggles the 2 <input> [readonly] attributes function editRow(e) { e.target.classList.toggle('open'); const row = e.target.closest('tr'); const inputs = row.querySelectorAll('input'); inputs.forEach(inp => { inp.toggleAttribute('readonly'); inp.classList.toggle('open'); }); } // Formats a value into a float with 2 decimal places function format(e) { if (e.target.matches('[name="tilt"].open')) { e.target.value = parseFloat(e.target.value).toFixed(2); } }
 html { font: 300 2.5vmin/1 'Segoe Ui'; } table { table-layout: fixed; border-collapse: collapse; width: 96%; } th { border-bottom: 3px solid black; } th:first-of-type, th:nth-of-type(2) { width: 11rem; } th:nth-of-type(3) { width: 17rem; } th:nth-of-type(4) { width: 13rem; } th:nth-of-type(5) { width: 9rem; } td { text-align: center; padding: 4px; } input, select, button { display: inline-flex; align-items: center; font: inherit; } button { cursor: pointer; } input { border: 0; } .open { border-radius: 4px; outline: 3px inset blue; outline-offset: 1px; } [name="tilt"] { width: 9rem; text-align: right; font-family: Consolas; } [name="comment"] { width: 17rem; } time { width: 10rem; }
 <form id='interface'> <table> <thead> <tr> <th>Benchmark</th> <th>Tilt</th> <th>Comment</th> <th>Time Log</th> <th><button name='btn' class='add' type='button'>➕ Add Row</button></th> </tr> </thead> <tbody class='data'></tbody> </table> </form>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM