首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可编辑表格单元

可编辑表格单元
EN

Stack Overflow用户
提问于 2022-07-22 15:15:26
回答 2查看 150关注 0票数 2

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

代码语言:javascript
复制
<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>
EN

回答 2

Stack Overflow用户

发布于 2022-07-22 19:50:41

如果您有多个窗体控件(例如。<input><select><button>等),将所有东西包装在<form>中。使用.classtagNamename[attribute]引用元素。正如您在下面的示例中所看到的,id仅用于引用<form>一次,但即使是这样,name也可以轻松地引用。

图I -布局

代码语言:javascript
复制
<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>

图2-引用元素

代码语言:javascript
复制
// 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

读取以下

事件

事件委托

内联事件处理程序是垃圾。

HTMLFormElement

HTMLFormControlsCollection

表单控件

详细信息在示例中有注释

代码语言:javascript
复制
/**
 * @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);
  }
}
代码语言:javascript
复制
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;
}
代码语言:javascript
复制
<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>

票数 1
EN

Stack Overflow用户

发布于 2022-07-22 15:41:07

原因是您将相同的in分配给多行中的控件(当用户添加行时)。

你应该做的是:

  1. 跟踪所有setAttribute(“id”)中控件的行数和附加行号。台词。示例:
代码语言:javascript
复制
superassetCell.setAttribute("id", "benchmarkcell");

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

getElementById根据定义为具有唯一id的元素工作。

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

检查这个问题

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73082579

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档