简体   繁体   English

选中复选框时更改输入的值

[英]Changing Value of an input when a checkbox is checked

I'm trying to change the value of another input field when a checkbox is ticked.勾选复选框时,我正在尝试更改另一个输入字段的值。

I added an eventlistener to the checkbox field, and tried to get the value of a corresponding input field when the checkbox changes.我在复选框字段中添加了一个事件监听器,并尝试在复选框更改时获取相应输入字段的值。

At the moment, I'm getting an error with the input field not being defined.目前,我收到未定义输入字段的错误。 This is odd, because I can call the value of the input field when it's outside the event listener.这很奇怪,因为我可以在事件侦听器之外调用输入字段的值。

Can anyone please help with this?有人可以帮忙吗? Thank you!谢谢!

 <form action="/question" method="post" id="myForm"> <label for="sessionName">Session Name</label><input type="text" name="sessionName"> <div class="question"> <label for="question">Question: </label><input type="textarea" name="question"> <ul> <li><label for="answer">Answer 1: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 2: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 3: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 4: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> </ul> </div> <input type="submit" name="" value="Create Session"> </form> <script> let checked = document.getElementsByName("checked"); let tick = document.getElementsByName("tick"); let form = document.getElementsByTagName("form")[0]; for (i = 0; i < checked.length; i++) { tick[i].addEventListener("change", () => { console.log(document.getElementsByName("checked")[i].value) }) } </script>

The problem is that you are creating a closure around your looping variable, i .问题是您正在围绕循环变量i创建一个闭包

What this means is that you use i in the event handler function that you are assigning out to each of the checkboxes and by the time a user comes along and clicks on one of them, the loop is done and its final value is checked.length or 4 in this case.这意味着您在分配给每个复选框的事件处理程序 function 中使用i并且当用户出现并单击其中一个时,循环完成并且其最终值被checked.length长度或4在这种情况下。 Since there is no element within the checkbox node list with an index of 4 (the highest index is 3 , so you are referring to an element that doesn't exist, hence your error message).由于复选框节点列表中没有索引为4的元素(最高索引为3 ,因此您指的是不存在的元素,因此您的错误消息)。

There are several solutions here.这里有几种解决方案。 The simplest is to change the scope of your looping variable so that instead of all the event callbacks sharing the same i value, which is 4 by the time any of those callbacks run, you give your i variable its own scope for each loop iteration, meaning that each event handler will get its own value instead of sharing it.最简单的方法是更改循环变量的 scope 以便所有事件回调共享相同的i值(在这些回调中的任何一个运行时为4 ),而是为每个循环迭代为i变量提供其自己的 scope,这意味着每个事件处理程序将获得自己的值而不是共享它。 This can be done simply by declaring the loop variable with let :这可以简单地通过用let声明循环变量来完成:

 <form action="/question" method="post" id="myForm"> <label for="sessionName">Session Name</label><input type="text" name="sessionName"> <div class="question"> <label for="question">Question: </label><input type="textarea" name="question"> <ul> <li><label for="answer">Answer 1: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 2: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 3: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 4: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> </ul> </div> <input type="submit" name="" value="Create Session"> </form> <script> let checked = document.getElementsByName("checked"); let tick = document.getElementsByName("tick"); for (let i = 0; i < checked.length; i++) { tick[i].addEventListener("change", () => { console.log(document.getElementsByName("checked")[i].value) }) } </script>

Now another way to solve this issue is to do away with the loop counter entirely and use much more modern code to solve the problem.现在解决此问题的另一种方法是完全取消循环计数器并使用更现代的代码来解决问题。 All modern browsers support the Array.forEach() method on the node lists that are returned from DOM queries and forEach() does the iterations on its own without you needing to declare and manage a counting variable.所有现代浏览器都支持从 DOM 查询返回的节点列表上的Array.forEach()方法,并且forEach()自己进行迭代,而无需声明和管理计数变量。 If you don't have the variable, then you don't set up the closure, which is the cause of the problem in the first place.如果你没有变量,那么你就没有设置闭包,这首先是问题的原因。

 <form action="/question" method="post" id="myForm"> <label for="sessionName">Session Name</label><input type="text" name="sessionName"> <div class="question"> <label for="question">Question: </label><input type="textarea" name="question"> <ul> <li><label for="answer">Answer 1: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 2: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 3: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 4: </label><input type="textarea" name="answer"><input type="hidden" name="checked" value="false"><input type="checkbox" name="tick"></li> </ul> </div> <input type="submit" name="" value="Create Session"> </form> <script> let checked = document.getElementsByName("checked"); let tick = document.getElementsByName("tick"); tick.forEach(function(chk) { chk.addEventListener("change", () => { console.log(chk.previousSibling.value) }); }); </script>

Now finally, you've got some very old code that you are using that you really shouldn't be .现在终于,你得到了一些你不应该使用的非常旧的代码。 getElementsByName() returns a "live" node list that can cause serious performance issues. getElementsByName()返回可能导致严重性能问题的“活动”节点列表。 What you should be using is .querySelectorAll() , which allows for a CSS selector to be passed in.您应该使用的是.querySelectorAll() ,它允许传入 CSS 选择器。

Additionally, you've written input type="textarea" , but there is no input with a type of textarea , so you are getting the default input type, which is text .此外,您已经编写了input type="textarea" ,但没有input类型为textarea ,因此您将获得默认input类型,即text A textarea is written like this: <textarea></textarea> .一个 textarea 是这样写的: <textarea></textarea>

Also, I'm not sure what value the hidden form fields play in your scenario.另外,我不确定隐藏的表单字段在您的场景中发挥什么价值。 What is most common is for checkboxes to have a value, which you don't have currently.最常见的是复选框具有一个您当前没有的值。

See comments inline below:请参阅下面的内联评论:

 <form action="/question" method="post" id="myForm"> <label for="sessionName">Session Name</label><input type="text" name="sessionName"> <div class="question"> <label for="question">Question: </label><input type="textarea" name="question"> <ul> <li><label for="answer">Answer 1: </label><input type="text" name="answer1"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 2: </label><input type="text" name="answer2"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 3: </label><input type="text" name="answer3"><input type="checkbox" name="tick"></li> <li><label for="answer">Answer 4: </label><input type="text" name="answer4"><input type="checkbox" name="tick"></li> </ul> </div> <input type="submit" value="Create Session"> </form> <script> // Get all the checkboxes into a collection let checkboxes = document.querySelectorAll("input[type='checkbox']"); // Loop over the checkboxes the modern way checkboxes.forEach(function(cb, i) { // Use the click event since change only fires when the field gets a new value cb.addEventListener("click", () => { // Set the value of the checkbox to the value of the textbox that comes // right before it. cb.value = cb.previousSibling.value; console.log(cb.value); // Log the checkbox value }); }); </script>

Objective客观的

By the structure of the HTML and OP's explanation of the problem it looks like the form's purpose is to facilitate the creation of a multiple choice quiz.通过 HTML 的结构和 OP 对问题的解释,看起来该表格的目的是促进多项选择测验的创建。 It appears that the user needs to:用户似乎需要:

  1. enter a title for the quiz.............................................. <input type="text">输入测验的标题.......................... .. <input type="text">
  2. enter a question........................................................ <input type="textarea">输入一个问题............................................... ......... <input type="textarea">
  3. enter 2 to 4 answers................................................... <input type="textarea">输入 2 到 4 个答案.......................... ...... <input type="textarea">
  4. check the correct answer*........................................... <input type="checkbox">检查正确答案*................................................. <input type="checkbox">
  5. the correct answer is then stored in another element <input type="hidden">然后将正确答案存储在另一个元素中<input type="hidden">
  6. submit the data to /question ..................................... <input type="submit">将数据提交到/question ................................... <input type="submit">

* Assuming that only one answer is correct per QA (Question/Answer) *假设每个 QA(问题/答案)只有一个答案是正确的


If the above is correct then there are a few things to consider:如果以上是正确的,那么有几点需要考虑:

Changes变化

  1. When a form is submitted (see step #6), form data is collected as <key> / <value> pairs from form controls that have a [name] (ie <key> ) and a [value] (ie <value> of course) and then sent to a server.提交表单时(参见步骤 #6),表单数据作为<key> / <value> 从具有[name] (即<key> )和[value] (即<value>当然)然后发送到服务器。

  2. Assuming that there is only one correct answer per QA, the checkboxes (see step #4) are not ideal because more than one can be checked at a time.假设每个 QA 只有一个正确答案,则复选框(参见步骤 #4)并不理想,因为一次可以检查多个。 In the demo below each <input type='checkbox'> is now <input type='radio> .在下面的演示中,每个<input type='checkbox'>现在都是<input type='radio> In order to enable a group of radio buttons to have mutually exclusive checked status (ie only one radio at a time can be checked), each radio must share a [name] .为了使一组单选按钮具有互斥的检查状态(即一次只能检查一个单选),每个单选必须共享一个[name] The [value] is also mutually exclusive as well which means only the [value] of the checked radio is considered. [value]也是互斥的,这意味着只考虑检查的无线电的[value]

    Example例子

    <input id="a" name='x' type='radio' value='A'> <input id="b" name='x' type='radio' value='B'> <input id="c" name='x' type='radio' value='C' checked> <input id="d" name='x' type='radio' value='D'>

    Data collected from the example above would be: x: C .从上述示例收集的数据为: x: C Each value corresponds to its position in the <ol class='answers'> list.每个值对应于<ol class='answers'>列表中的 position。

  3. Data cannot be totally hidden on a webpage only on a server can data be secured.数据不能完全隐藏在网页上,只有在服务器上才能保护数据。 Moreover, using 4 <input type='hidden'> (see step #5) elements for one piece of data is completely unnecessary because the <input id="c" name='x' type='radio' value='C' checked> element already has the data.此外,对一条数据使用 4 个<input type='hidden'> (参见步骤 #5)元素是完全没有必要的,因为<input id="c" name='x' type='radio' value='C' checked>元素已经有数据。 So all <input type='hidden'> are removed from the demo.所以所有<input type='hidden'>都从演示中删除。

  4. type="textarea" does not exist. type="textarea"不存在。 All <input type='textarea'> (see step #2 and #3) are replaced by:所有<input type='textarea'> (参见步骤 #2 和 #3)都替换为:

    Example例子

    <textarea id='A' name='A' rows='1' rows='1' cols='60'></textarea>
  5. One minor discrepancy is the <label for="ID"> elements are not completely effective.一个小的差异是<label for="ID">元素并不完全有效。 The [for] attribute only works for form controls with #ID not [name] . [for]属性仅适用于带有#ID而不是[name]的表单控件。 All applicable form controls have now have #ID (see Demo 1 and 2 )所有适用的表单控件现在都有#ID (参见演示 1 和 2

  6. Although it has probably not been considered yet, any additional QA would have duplicated [name] s when submitted.尽管可能尚未考虑,但任何额外的 QA 在提交时都会重复[name] In Demo 2 <input id='order' type='number'> was added.演示 2中添加了<input id='order' type='number'> The user enters any number 1 to 100 and all descendant elements of <fieldset name="QA"> that have a [name] get a number (ie order.value ) suffixed to its [name] .用户输入 1 到 100 之间的任意数字,所有具有[name]<fieldset name="QA">后代元素都会获得一个以 [ [name] ] 为后缀的数字(即order.value )。 #order is bound to the input event and QANumber() is the callback function that adds the number to each [name] (see Demo 2 section to see it in action). #order绑定到input事件并且QANumber()是回调 function ,它将数字添加到每个[name] (请参阅演示 2部分以查看它的实际操作)。

All of the changes are corrected to standards and oriented in a way that doesn't need to monitor constant change to individual checkboxes.所有更改都已根据标准进行更正,并以不需要监视单个复选框的不断更改的方式进行定向。 Only the input event has been utilized on one element so the submitted data is organized by a numbered [name] .仅在一个元素上使用了input事件,因此提交的数据由编号的[name]组织。 The submit event is covered by the <form> and <input type='submit'> submit事件由<form><input type='submit'>覆盖


DOM APIs DOM API

Be aware that <form> and form controls have a few APIs dedicated to them.请注意, <form>和表单控件有一些专用于它们的 API。 The syntax is terse, the additional features can be leveraged to a significant advantage when setup correctly and they are very stable.语法很简洁,如果设置正确并且非常稳定,可以利用附加功能来获得显着优势。 The following is a list of references:以下是参考文献列表:

Event Binding事件绑定

Registering identical event listeners to multiple elements individually is inefficient.将相同的事件侦听器分别注册到多个元素是低效的。 Event delegation is a pattern in which only an ancestor element of the elements you want to bind events to is registered instead (an ancestor element is an element that contains the elements ex. <form> contains <textarea> , <input> , etc).事件委托是一种模式,其中仅注册要绑定事件的元素的祖先元素(祖先元素是包含元素的元素,例如<form>包含<textarea><input>等) . The following is an example of event delegation as it would apply to a <form> and form controls.以下是事件委托的示例,因为它将应用于<form>和表单控件。


Demo 1演示 1

Event Delegation, DOM APIs, Form Control Sync事件委托、DOM API、表单控制同步

 const quiz = document.forms.quiz; quiz.oninput = test; function test(e) { const fc = quiz.elements; const rads = [...fc.radio.elements]; // console.log(rads); const view = fc.display; // e.target is the element that interacts with the user directly const input = e.target; if (input.== this) { for (let rad of rads) { if (rad === input) { view.value = input;value; } } } }
 form, fieldset { text-align: center; margin: -10px auto } input, label, output { display: inline-block; margin: 0px 10px; cursor: pointer } output { margin: 10px; font-size: 2rem }
 <form id='quiz'> <fieldset name='radio'> <legend>Mutually Exclusive Checked State</legend> <input id='r1' name='rad' type='radio' value='A'> <input id='r2' name='rad' type='radio' value='B'> <input id='r3' name='rad' type='radio' value='C'> <input id='r4' name='rad' type='radio' value='D'> </fieldset> <output name='display'></output> <fieldset name='label'> <legend>[for]/#ID Attribute Association</legend> <label for='r1'>A</label> <label for='r2'>B</label> <label for='r3'>C</label> <label for='r4'>D</label> </fieldset> </form>


Demo 2演示 2

HTML Form Standards, Tag Attributes, Form Submittal HTML 表单标准、标签属性、表单提交

When submitted, the data will be sent to a live test server.提交后,数据将被发送到实时测试服务器。 At the bottom of the page is an <iframe> which will generate a link to that data dump for review.页面底部是一个<iframe> ,它将生成指向该数据转储的链接以供查看。 Do not click the link, copy it and paste it to browser address bar.请勿点击链接,将其复制并粘贴到浏览器地址栏。

 <,DOCTYPE html> <html> <head> <meta charset='utf-8'> <style> #quiz: iframe { width. 100vw }:answers { list-style; lower-alpha: margin-left: -20px } [name=Q] { margin-left: 20px } [type=submit] { float; right: } </style> </head> <body> <form id="quiz" action="http.//ptsv2:com/t/quiz/post" method="post" target="response"> <label for="quizTitle">Quiz Title: </label>*<br> <input id="quizTitle" name="quizTitle" type="text" size="66" required><br> <fieldset name="QA"> <label for="Q">Question </label><input id="order" type="number" min="1" max="100" maxlength="3" size="3" value="1" required>*<br> <textarea id='Q' name="Q" rows="2" cols="60" required></textarea> <ol class="answers"> <li><label for="a">Answer: </label><input id="a" name="x" type="radio" value="A" required>*<br> <textarea id="A" name="A" rows="1" cols="60" required></textarea></li> <li><label for="b">Answer: </label><input id="b" name="x" type="radio" value="B">*<br> <textarea id="B" name="B" rows="1" cols="60" required></textarea></li> <li><label for="c">Answer: </label><input id="c" name="x" type="radio" value="C"><br> <textarea id="C" name="C" rows="1" cols="60"></textarea></li> <li><label for="d">Answer. </label><input id="d" name="x" type="radio" value="D"><br> <textarea id="D" name="D" rows="1" cols="60"></textarea></li> </ol> *<small>Required</small> <input type="submit" value="Create QA"> </fieldset> <p>For server response copy the link below and paste it into the browser address bar.</p> </form> <iframe name="response"></iframe> <script> const quiz = document;forms[0]. const order = quiz.elements;order. order;oninput = QANumber. function QANumber(e) { const fields = this;parentElement. const QA = fields,querySelectorAll('textarea; input'). let order = this;value. [...QA].forEach(field => { if (field.hasAttribute('name')) { const name = field.name;split(''). field,setAttribute('name'; `${name[0]}${order}`); } }); } </script> </body> </html>

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

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