【问题标题】:How can I dynamically generate input fields with Javascript and then use their values?如何使用 Javascript 动态生成输入字段,然后使用它们的值?
【发布时间】:2015-01-07 06:15:33
【问题描述】:

我希望能够在提交时找到courseAmount输入字段的数值,然后通过onsubmit方法生成新的输入字段(到initialForm下面的hourForm表单中)在 javascript 中,然后在提交 hourForm 表单时从每个生成的输入字段中检索值并将这些值放入数组中。

但是,我在使用 javascript 实际生成输入字段时遇到了困难,我怀疑我在检索 courseAmount 输入的值并将其移植到我的 createInput() 函数时遇到了困难,但我'不确定这是否是问题所在。

这是我的 HTML:

<!DOCTYPE html>
<head>
  <link rel="stylesheet" href="css/main.css">
</head>
<body>
  <form id="initialForm" method="post" onsubmit="createInput()" action="">
    <label>Number of hours for which you would like to study</label>
    <input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1"/>
    <label>Number of courses you would like to study for</label>
    <input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1"/>
    <input type="submit" class="submitStudy" value="Submit"/>
  </form>
  <form id="hourForm" method="post" onsubmit="calcHours">
    <label>State the desired time spent working in each course</label>
  </form>
</body>

这是我的 Javascript:

var notedOverallHours = document.getElementById("overallHours").value * 60; 
var courseNumberTotal = document.getElementById("courseAmount").value;
var counter = 0;

function createInput() {
  var newForm = document.getElementById("hourForm");
  document.getElementById("initialForm").style.display = "none";
  document.getElementById("hourForm").style.display = "block";

  for (i = 0; i <= courseNumberTotal; i++) {
    newForm.innerHTML = "<label>Course #" + (counter + 1) + "</label>" + "<input type='number' name='courseHours' class='newInputs' min='1' max='9' step='1' value='1'/>";
    counter++;
  }
  newForm.innerHTML = "<input type='submit' value='submit'/>";
}

有人可以帮我弄清楚这个 Javascript 吗?我的 JSFiddle 尝试是徒劳的,因为 JSFiddle 不喜欢重新加载页面的表单。

谢谢!

【问题讨论】:

    标签: javascript arrays forms function


    【解决方案1】:

    来自关于 innerHTML 的 mdn 页面:“删除元素的所有子元素,解析内容字符串并将结果节点分配为元素的子元素。” https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML

    一般来说,您根本不想使用innerHTML。几乎总是有更好的方法。在这种情况下,这将是 createElement 和 appendChild。

    此外,没有“onsubmit”方法。你这样调用的是一个 HTML 属性,它为 submit 事件注册一个处理程序。 http://www.quirksmode.org/js/introevents.html

    但是使用 html 属性有其严重的缺点:http://www.quirksmode.org/js/events_advanced.html

    考虑到所有这些,我会这样做:http://jsfiddle.net/ashnur/rwod4z1d/

    HTML:

    <form id="initialForm" method="post" action="">
        <label>Number of hours for which you would like to study</label>
        <input type="number" name="overallHours" id="overallHours" class="stored" min="1" max="20" step="1" value="1" /><hr>
        <label>Number of courses you would like to study for</label>
        <input type="number" name="courseAmount" id="courseAmount" class="stored" min="1" max="20" step="1" value="1" /><hr>
        <input type="submit" class="submitStudy" value="Submit" />
    </form>
    <form id="hourForm" method="post" >
        <label>State the desired time spent working in each course</label><hr>
    </form>
    

    js:

    var notedOverallHours = document.getElementById("overallHours").value * 60;
    var courseNumberTotal = document.getElementById("courseAmount").value;
    var counter = 0;
    
    var initialForm = document.getElementById("initialForm");
    var hourForm = document.getElementById("hourForm");
    
    initialForm.addEventListener('submit', createInput);
    hourForm.addEventListener('submit', calcHours);
    
    function calcHours() {}
    
    function createInput(ev) {
        ev.preventDefault(); // this is not needed if you are using a bare button and the click event
        var newForm = document.getElementById("hourForm");
        initialForm.style.display = "none";
        hourForm.style.display = "block";
    
        for (i = 0; i <= courseNumberTotal; i++) {
            addControl(newForm, "Course #" + (counter + 1));
            counter++;
        }
        var submit = document.createElement('input');
        submit.type = 'submit';
        submit.value = 'submit';
        newForm.appendChild(submit);
    }
    
    function addControl(form, labelText) {
        var label = document.createElement('label');
        var input = document.createElement('input');
        var hr = document.createElement('hr');
        input.type = 'number';
        input.name = 'courseHours';
        input.classname = 'newInputs';
        input.min = '1';
        input.max = '9';
        input.step = '1';
        input.value = '1';
        label.textContent = labelText;
        form.appendChild(label);
        form.appendChild(input);
        form.appendChild(hr);
    
    
    }
    

    【讨论】:

      【解决方案2】:

      正如 Tobias 正确指出的那样,您的表单提交事件被允许继续,这会导致页面刷新和所有纯 JavaScript 数据的“重置”。此外,您不是在表单提交时(在用户输入金额之后)捕获您的值(notedOverallHourscourseNumberTotal),而是在您的页面初始化时(在用户输入任何内容之前 )。

      所以,要解决这个问题,首先对您的 HTML 进行微小的修改:

      ...
      <form id="initialForm" method="post" action="">
      ...
      

      请注意,我从您的表单中删除了 onsubmit 属性。我们可以通过 JavaScript 本身的事件来捕获它。

      接下来将一个事件侦听器附加到您的表单,以防止它提交并调用您的 createInput() 函数:

      document.getElementById("initialForm").addEventListener('submit', function (e) {
        e.preventDefault();
        createInput();
      });
      

      这将附加一个eventListener,用于侦听您的initialForm 元素上的submit 事件。第一个参数是您要监听的事件类型(本例中为submit),第二个参数是您要触发的回调。

      回调函数总是获取传入的事件(e 参数)。通过在此事件上调用 preventDefault,我们可以阻止它冒泡并实际导致页面刷新。

      接下来我们调用createInput()函数,经过一些修改后,如下所示:

      function createInput() {
        var notedOverallHours = document.getElementById("overallHours").value * 60; 
        var courseNumberTotal = document.getElementById("courseAmount").value;
        var newForm = document.getElementById("hourForm");
      
        document.getElementById("initialForm").style.display = "none";
        document.getElementById("hourForm").style.display = "block";
      
        // Add our elements
        for (i = 1; i <= courseNumberTotal; i++) {
          var child = document.createElement('li');
          child.innerHTML = "<label>Course #" + (i) + "</label>" + "<input type='number' name='courseHours-"+ i+"' class='newInputs' min='1' max='9' step='1' value='1'/>";
          newForm.appendChild(child);
        }
      
        // Add our button
        var button = document.createElement('li');
        button.innerHTML = "<input type='submit' value='submit'/>";
        newForm.appendChild(button);
      }
      

      如您所见,我在createInput() 函数中捕获了notedOverallHourscourseNumberTotal 变量,因此它们将携带表单提交事件期间设置的任何值。

      然后我们遍历每个课程编号。我们不是替换innerHTML,而是首先创建一个元素(在我们的例子中为li)并用HTML 字符串填充该元素。接下来我们将此子元素附加到父表单。

      在循环内我删除了counter 变量,因为您可以在循环内简单地使用i 的值,无需创建额外的变量。我还用i 为每个孩子附加了name 属性,以免出现任何名称冲突。

      在函数结束时,我们只需创建并附加一个包含提交按钮的新 li 元素。

      您可以通过使用createElement 函数实际创建labelinput 元素并使用普通的JavaScript 设置器单独设置其属性和text 来进一步优化这一点,而不是将li 元素中的所有内容转储为我在这里做的是为了让事情变得更简单一些。我会把它留作练习:)

      我用这个确切的代码 here 创建了一个粗略的 JSFiddle。

      【讨论】:

      • 谢谢!这正是我一直在寻找的。我会用你在这里给我的东西做一些研究和练习:)。其他人都有很好的答案,但@Timusan 以一种易于理解和解释最佳实践的方式表达了措辞
      • 你的意思是他给了解决方案?
      • onsubmit 不能是“真正的方法”,您的术语不存在。你可能想说这是一个现有的功能,我相信。但是,您仍然不应该使用“onsubmit”html 属性来附加事件处理程序,而应该使用 addEventListener DOM 方法。方法是绑定到对象的那些函数。也就是说,它们隐藏的this 参数不是全局的,除非我们谈论的是全局上的方法。无论如何,onsubmit 是一个属性,而不是一个方法。
      • @user3172050 我们所有的答案都包含解决您的“难题”部分的体面信息。因此,我强烈建议您也仔细阅读 Ashnur 和 Tobias 的回答,以详细了解为什么您的代码没有按照您希望的方式运行。
      • @Ashnur 由于 OP 的问题不是一个单一的问题,而是相当多的误解(他问 有人能帮我弄清楚这个 Javascript 吗?),唯一合乎逻辑的要做的是提供一个可行的解决方案解释所犯的每个错误。是否将其用作替代品是他的决定,最重要的是,他现在有足够的把手可以掌握并从工作示例代码中学习。那将是SO的重点。而且,如前所述,您和 Tobias 的回答只会对这些知识有所帮助。
      【解决方案3】:

      createInput() 函数被调用时,你没有得到想要的结果,因为你在循环的每次迭代中都重置了newForm.innerHTML,然后在结束时再次重置。而不是使用=,您应该使用+= 来附加所需的文本,而不是替换现有的文本。

      // Replacing the contents of newForm.innerHTML
      newForm.innerHTML = "foo";
      
      // Appending to newForm.innderHTML (You want to do this)
      newForm.innerHTML += "foo";
      

      另一个问题是,当您按下提交时,页面在createInput() 能够获得所需结果之前重新加载。您很可能希望在按下提交按钮时停止页面实际提交并因此重新加载。为此,您可以将表单的onsubmit 属性更改为"return createInput()",然后将return false; 行添加到createInput() 函数的末尾,以向浏览器表明您不希望提交表单。

      【讨论】:

      • 谢谢!我对 JS 还很陌生,所以其中一些内容令人困惑。无论如何,我今晚已注销,但我会在今天晚些时候听从您的帮助并更新反馈和投票。
      • @user3172050 没问题的朋友,如果您需要更多帮助,请告诉我!
      猜你喜欢
      • 2016-09-15
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 1970-01-01
      • 2020-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多