如何使用 Javascript 动态生成输入字段,然后使用它们的值

How can I dynamically generate input fields with Javascript and then use their values?

本文关键字:然后 字段 Javascript 何使用 动态 输入      更新时间:2023-09-26

我希望能够在提交时找到courseAmount输入字段的数值,然后通过 javascript 中的 onsubmit 方法生成新的输入字段(到initialForm下方的hourForm表单中),然后在提交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不友好地重新加载页面。

谢谢!

来自关于

innerHTML 的 mdn 页面:"删除所有元素的子级,解析内容字符串并将生成的节点分配为元素的子级。 https://developer.mozilla.org/en-US/docs/Web/API/Element.innerHTML

一般来说,你根本不想使用innerHTML。几乎总是有更好的方法。在本例中,这将是 createElement 和 appendChild。

此外,没有"提交"方法这样的东西。您像这样调用的是一个 HTML 属性,该属性为提交事件注册处理程序。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);

}

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

因此,要解决此问题,首先对您的HTML进行微小的修改:

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

请注意,我从表单中删除了 onsubmit 属性。我们可以在 JavaScript 本身中用一个事件来捕捉这一点。

接下来,将

事件侦听器附加到表单,以防止它提交并调用createInput()函数:

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

这将附加一个侦听initialForm元素上的submit事件的eventListener。第一个参数是您要侦听的事件类型(在本例中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变量,因此它们将携带在表单提交事件期间设置的任何值。

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

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

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

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

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

调用 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()函数的末尾,以向浏览器指示您不希望提交表单。

相关文章: