如何使用EventListener更改元素的值

时间:2019-06-20 22:35:13

标签: javascript html

在此程序中,我可以使用按钮添加输入,但是我需要显示每个输入的长度(更改时)。我可以使用EventListener来获取长度,但是我不确定如何更改任何新创建的按钮的文本值。

在第12行,您可以看到我能够在第一个输入上成功更改值,但是我使用的是html变量。如果查看我的addCell()函数,您会看到我有一个元素作为每个节点的子代来跟踪每个输入的长度。我需要在change()函数中访问该元素,以便将event.target.value.length设置为相应的节点子元素。

我尝试使用它,设置var x = this,并且我尝试使用event.target属性来找到相应的节点,甚至是innerHTML。

var i = 0;
var count = 1;
var length = 2;
var chars = 0;

document.addEventListener('input', function (evt) {
  change(evt);
});

function change(elem) {
  var check = document.getElementById("first");
  if (event.target == check) {
    document.getElementById("len").innerHTML = event.target.value.length;
    return;
  }

  // Here's where I'm stuck

}

function removeCell() {
  if (count <= 1) {
    alert("Illegal operation, the police have been notified.")
    return;
  }
  var elem = document.getElementById('main');
  elem.removeChild(elem.lastChild);
  count = count - 1;
  length = length - 1;
}

function addCell() {
  var node = document.createElement('div');
  node.innerHTML += length;
  var inp = document.createElement('INPUT');
  var size = document.createElement('size');

  inp.setAttribute("type", "text");
  node.appendChild(inp);
  node.appendChild(size);
  document.getElementById('main').appendChild(node);

  count += 1;
  length += 1;
  i += 1;
}
#area {
  width: 585px;
  background-color: lightgrey;
  color: black;
  border-style: solid;
  margin-left: auto;
  margin-right: auto;
  min-height: 100px;
  height: auto
}
#texts {
  width: 220px;
  height: 50px;
  border-style: solid;
}
body {
  background-color: grey;
}
<div id="area">
  <form id="main">
    <pre><b>          input </b>          length</pre>
    <span id="list">
      1<input type="text" id="first"> <var id="len"></var>
    </span>

  </form>
  <br />
  <button onclick="addCell()">Add Cell</button>
  <button onclick="removeCell()">Remove Cell</button>
  <button onclick="sort()">Sort</button>
</div>

由于每次更改后,我都可以使用alert()向我显示每个新创建的输入的正确长度,所以我知道有一种方法可以访问我创建的“ size”元素,并使用event.target对其进行更新.value.length

2 个答案:

答案 0 :(得分:1)

您的问题是您使用“全局”输入事件侦听器,并且您的change()函数未编程为处理多个输入字段,因为您正在其中查询已知的元素ID first和{{1 }}。

如果要使用全局侦听器,则必须告诉len函数如何访问新输入和相应的目标字段。

一种更简单的方法是修改change()函数并将事件侦听器附加到要创建的输入字段,而不是使用全局函数。因此,每个输入字段都拥有自己的事件监听器。由于输入字段和显示输入值长度的size元素都是在同一范围内创建的,因此可以轻松地将长度写入相应的size元素。

addCell()

如果您希望它与您提供的HTML一起使用,则需要删除第一个输入字段并手动调用inp.addEventListener('input', function(){ size.innerText = inp.value.length; }); ,以便呈现您的初始输入。

然后您的代码应如下所示(注意:我设置了addCell()var count = 0;):

var length = 1;
var i = 0;
var count = 0;
var length = 1;
var chars = 0;

function removeCell() {
  if (count <= 1) {
    alert("Illegal operation, the police have been notified.")
    return;
  }
  var elem = document.getElementById('main');
  elem.removeChild(elem.lastChild);
  count = count - 1;
  length = length - 1;
}

function addCell() {
  var node = document.createElement('div');
  node.innerHTML += length;
  var inp = document.createElement('INPUT');
  var size = document.createElement('size');

  inp.setAttribute("type", "text");
  inp.addEventListener('input', function(){
    size.innerText = inp.value.length;
  });
  node.appendChild(inp);
  node.appendChild(size);
  document.getElementById('main').appendChild(node);

  count += 1;
  length += 1;
  i += 1;
}

addCell();
#area {
  width: 585px;
  background-color: lightgrey;
  color: black;
  border-style: solid;
  margin-left: auto;
  margin-right: auto;
  min-height: 100px;
  height: auto
}
#texts {
  width: 220px;
  height: 50px;
  border-style: solid;
}
body {
  background-color: grey;
}

答案 1 :(得分:1)

  • 如果计划了HTML布局并且该布局是一致的,则可以将[name]属性用于表单控件和.class甚至仅使用tagName。处理多个标签时使用#id既困难又不必要。以防万一您不了解此关键规则: #ids必须是唯一的,同一页上不能有重复的#ids。重复使用#ids会在90%的时间内破坏JavaScript / jQuery。

  • 要通过.class#id[name]tagName等访问标签,请将document.querySelector()document.querySelectorAll()用于多个标签。

  • 要通过[name]#id访问表单和表单控件(输入,输出,选择等),请使用HTMLFormElement and HTMLFormControlsCollection APIs

  • .innerHTML具有破坏性,因为它会覆盖标记中的所有内容。 .insertAdjacentHTML()是非破坏性的,可以将htmlString放在标签内或标签周围的4个不同位置。

  • 事件处理程序和事件侦听器仅对页面加载时最初在页面上的标签起作用。之后动态添加的任何标签都无法注册以侦听/处理事件。您必须通过注册自加载页面以来一直在页面上的祖先标记来委派事件。这是通过delRow()完成的,因为按钮是在每行上动态创建的(更改此按钮是因为一个删除按钮删除了最后一行并没有什么用处,例如7行,您只需要删除4行就可以了)到第三行)。

  • 以下是详细信息:[...ui.len] ui引用所有表单控件.len是带有[name=len]的所有标记。方括号和spread operator将len标签的集合转换为数组。

  • 没有<size></size>这样的东西。因此document.createElement('size')是非常错误的。

const main = document.forms.main;

main.oninput = count;
main.elements.add.onclick = addRow;
document.querySelector('tbody').onclick = delRow;

function count(e) {
  const active = e.target;
  const ui = e.currentTarget.elements;
  const row = active.closest('tr');
  const idx = [...row.parentElement.children].indexOf(row);
  const length = [...ui.len][idx];
  length.value = active.value.length;
  return false;
}

function addRow(e) {
  const tbody = document.querySelector('tbody');
  let last = tbody.childElementCount+1;
  tbody.insertAdjacentHTML('beforeend', `<tr><td data-idx='${last}'><input name='txt' type="text"></td><td><output name='len'>0</output></td><td><button class='del' type='button'>Delete</button></td>`);
  return false;
}

function delRow(e) {
  if (e.target.matches('.del')) {
    const row = e.target.closest('tr');
    let rows = [...row.parentElement.children];
    let qty = rows.length;
    let idx = rows.indexOf(row);
    for (let i = idx; i < qty; i++) {
      rows[i].querySelector('td').dataset.idx = i;
    }
    row.remove();
  }
  return false;
}
      
    
    
body {
  background-color: grey;
}

#main {
  width: 585px;
  background-color: lightgrey;
  color: black;
  border-style: solid;
  margin-left: auto;
  margin-right: auto;
  min-height: 100px;
  height: auto
}

tbody tr td:first-of-type::before {
  content: attr(data-idx)' ';
}
<form id="main">
  <table>
    <thead>
      <tr>
        <th class='txt'>input</th>
        <th class='len'>length</th>
        <th><button id='add' type='button'>Add</button></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td data-idx='1'><input name='txt' type="text"></td>
        <td><output name='len'>0</output></td>
        <td><button class='del' type='button'>Delete</button></td>
      </tr>
    </tbody>
  </table>
  <!--These are dummy nodes because of the
  HTMLFormControlsCollection API ability to use id or name, there
  must be at least 2 tags with the same name in order for it to
  be considered iterable-->
  <input name='txt' type='hidden'>
  <input name='len' type='hidden'>
</form>