Iterate DOM property x times with JS - javascript

I basically have an input of type number
<input type="number" id="no_pi" name="" onkeyup="des()">
<div id="extract"></div>
and function
function des() {
var ext = document.getElementById('extract');
var va = Number(document.getElementById('no_pi').value);
for (var i = 0; i = va; i++) {
ext.innerHTML = "<input type='number' name='' class='form-control'><div class='input-group-text'>cm</div>";
}
}
I just want to instantly generate x number of inputs in div based on user input.
When the user input any number, the page just crashes down. I think the page is going in infinite loop, but I think it is not the case.
Any idea how to achieve this

There's several errors :
In your loop : i = va (this is why it crashes)
You erase the content of the div ext each time you iterate, instead of adding content
By listening on keyup event, you add some content on each key hit. Finally if the user submit 12, it will generate 1 + 12 elements. You should pass the value using a form (by doing this you can also add easily the value control in the input element).
As perfectly mentionned by #Andy in the comments, innerHTML += is a very bad idea. You should generate your elements using document.createElement or insertAdjacentHTML.
Some advices :
Use an event listener instead of the onkeyup attribute
Avoid this kind of variable names, be more explicit
Use const and let instead of var
Here's a version which fixes all that issues :
document.getElementById('elementsNumberForm').addEventListener('submit', event => {
event.preventDefault();
const targetElement = document.getElementById('extract');
const inputValue = document.getElementById('no_pi').value;
for (let i = 0; i < inputValue; i++) {
targetElement.insertAdjacentHTML('beforeEnd', '<input type="number" name="" class="form-control" /><div class="input-group-text">cm</div>');
}
});
<form id="elementsNumberForm">
<input type="number" id="no_pi" min="1" />
<input type="submit" />
</form>
<div id="extract"></div>

Your key issue is how you're using your loop. i = va isn't going to accomplish what you want. It should be a check that the index in the iteration is less than the number represented by the value in your input. It should be i < va.
The other issue is that you're not adding to the HTML, just ensuring that the HTML is just one input.
I've adjusted the code in your question to remove the inline JS and use addEventListener instead, and also to use an array to store the HTML built from the loop which can then be applied to the extract element.
// Cache the elements outside of the loop
// and attach a change listener to the noPi element
const extract = document.getElementById('extract');
const noPi = document.getElementById('no_pi');
noPi.addEventListener('change', des, false);
function des() {
const limit = noPi.value;
// Check that we haven't gone into
// negative numbers
if (limit >= 0) {
// Create an array
const html = [];
// Loop, pushing HTML into the array, until
// we've reached the limit set by the value in noPi
for (let i = 0; i < limit; i++) {
html.push('<input type="number" class="form-control"><div class="input-group-text">cm</div>');
}
// `join` up the array, and add the HTML
// string to the extract element
extract.innerHTML = html.join('');
}
}
<input type="number" id="no_pi" />
<div id="extract"></div>
Additional information
join

I see that you want to use an input field to insert the number of inputs to create.
I see a better way to start learning insert the number of inputs with a prompt, and then scale the project.
You can start like this: (hope it make sense to you)
<div style="height: 300px; background-color: #ccc;" class="container"></div>
we have this div that is going to be filled with the inputs
Then we have the script:
const container = document.querySelector('.container');
const runTimes = prompt("How many inputs wnat to create?");
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
In the for loop, we create the element input, then with the .innerHTML we add the HTML we want. to end the loop, we need to append the created input element to the div we have.
hope it makes sense to you, :)
when you get the idea with the prompt , I´ve done this project more pro jaja.
<div style="height: 300px; background-color: #ccc;" class="container"></div>
<input type="text" class="numberTimes" onkeyup="getValue()">
we add an event listener to the input with the function getValuue, and the script like this:
const container = document.querySelector('.container');
function getValue(){
let runTimes = document.querySelector('.numberTimes').value;
document.querySelector('.numberTimes').value= "";
for(let i = 0; i < runTimes; i++){
let newInput = document.createElement('input');
newInput.innerHTML = "<input type='number' name='' class='form-control'>";
container.appendChild(newInput);
}
}
This line document.querySelector('.numberTimes').value= ""; is to reset the input field.
So whenever insert a value on the input it creates that number of inputs in the container and cleans the input field :)

Related

Trying To Move Input Element to Another Div

I am creating a form that shows one question at a time. I would like to show all questions, though, on a different view when "View Complete Form" is clicked. The problem I am having is showing the questions in said form. There's no issue with the single view questions.
I am able to display the value, on said form but I cannot actually enter anything. That's not what I want.
Ex. in case any one is confused:
(In single view)
Question 1: (input box) Answer 1
(In full view)
Question 1: Answer 1 (All text, no input boxes)
I would like to do:
(In single view)
Question 1: (input box) Answer 1
(In full view)
Question 1: (input box) Answer 1
Like I said, I see how I can get the value (I used answer[i-1] = document.getElementById(i-1).value) then I print the answer BUT WITHOUT THE INPUT BOX.
I realized my mistake so I tried document.getElementById(x) which gives me [object HTMLInputElement]. Again, I just want the input box with the answer already filled in IF it's filled on the single view.
Did some searching on here and tried to use appendTo, descendants and appendChild (object does not support these) but nothing helped.
html
<div id="questionnaire-question">Click 'Start' to begin...</div>
<div id="input-questionnaire">
<input type='text' class='form-control' name='reqEng' id='1' style="display:none" placeholder="Requesting Engineer" required>
</div>
<button id="view-form" onclick="viewForm()">View Complete Form</button>
<form id="full-form" style="display:none">
<div id="full-form-question"></div>
<input type="reset" name="reset" value="Reset Fields">
<input type="submit" name="submit" id="submitQuestionnaire" value="Submit Questionnaire">
</form>
</div>
js
function viewForm() {
for (var x = 0; x < 44; x++) {
//form.appendChild(document.getElementById(x)); // Didn't work
//form.insert(document.getElementById(x).descendants()[x]); // Not supported
//document.getElementById(x).style.display = "block"; // Loop for questions and answers to populate
//document.getElementById(x+1).appendTo(form);
//fullForm.innerHTML += questions[x]+ ": " + answer[x+1] + " <br>";
fullForm.innerHTML += questions[x] + ": " + document.getElementById(x + 1) + " <br>";
}
}
This is what I want (from a previous form. I populated the inputs in an array but found it easier with some functionalities if I had just hard coded it)
https://imgur.com/cgarzSd
This is what I currently have :
https://imgur.com/Uj4FlvZ
Your question could possibly use some clarification, however I am taking a stab at it hoping that we can get you on the right track.
Below is an example of simply moving the input from one div to another:
function viewForm(){
//gets all of the inputs held in the "input-questionnaire" div
var inputs = document.getElementById('input-questionnaire').getElementsByTagName('input');
//loop through the collection of inputs
for(var i = 0;i < inputs.length; i++)
{
//if you want to ensure input is no longer hidden when moved
//inputs[i].style.display = "block";
//move the element to the new div
document.getElementById("full-form-question").appendChild(inputs[i]);
}
//probably want to show the hidden form at this point
document.getElementById("full-form").style.display = "block";
}
Here is another option if you actually want to "copy" the input to the new div:
function viewForm(){
//gets all of the inputs held in the "input-questionnaire" div
var inputs = document.getElementById('input-questionnaire').getElementsByTagName('input');
//loop through the collection of inputs
for(var i = 0;i < inputs.length; i++)
{
//clone the current input
var clone = inputs[i].cloneNode();
//make sure the question is visible?
clone.style.display = "block";
//append the clone to your "full-form-question" div
document.getElementById("full-form-question").appendChild(clone);
}
//probably want to show the hidden form at this point
document.getElementById("full-form").style.display = "block";
}
Hope this helps. Cheers!
Here's a basic example of how you can "move" input elements from one form to another. In reality you're making a copy of it and removing the old one from the previous form.
It looks like the main problem you're having is that you're not defining the form.
Take a look at how you could go about it:
function viewForm() {
const form1 = document.getElementById('form-1')
const form2 = document.getElementById('form-2')
for (var x = 1; x <= 1; x++) {
let input = document.getElementById(x)
form1.remove(input)
form2.append(input);
const span = document.createElement('span');
span.innerText = `${x} is now in form2`
form2.appendChild(span)
}
}
document.getElementById("btnMove").addEventListener('click', viewForm);
<div>
Form 1
<form id="form-1">
<input type='text' class='form-control' name='reqEng' id='1' placeholder="Requesting Engineer" required>
</form>
</div>
<div>
Form 2
<form id="form-2">
</form>
</div>
<input type="button" id="btnMove" value="move input">

Adding form post/submit button to javascript script

I found this code on here (thanks to Xavi López) and it is ideal for what I need to add to my project but I'm in need of some help adding a Form post and submit button in JavaScript. I have no knowledge on this subject and I've tried looking at some example but non of them seem to work. I would be grateful if someone could help me. After the user adds the relevant number of input boxes and adds there data, I would like to have a submit button which will POST the results to another web page (result page)
I have added the solution to the below coding (thank you MTCoster) but I'm now try to find a solution to having the submit button appear only when an entry has been added. I have tried different methods but non will work.
function addFields() {
// Number of inputs to create
var number = document.getElementById('member').value;
// Container <div> where dynamic content will be placed
var container = document.getElementById('container');
// Clear previous contents of the container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for (i = 0; i < number; i++) {
// Append a node with a random text
container.appendChild(document.createTextNode('Member ' + (i + 1) + ' '));
// Create an <input> element, set its type and name attributes
var input = document.createElement('input');
input.type = 'text';
input.name = 'member' + i;
container.appendChild(input);
// Append a line break
container.appendChild(document.createElement('br'));
}
}
<input type="text" id="member" name="member" value="">Number of Pins: (max. 48)<br>
Add Pinout Entries
<form action="result.asp" method="POST">
<div id="container"></div>
<input type="submit" value="Add Data">
</form>
You’re almost there - all you need to do is wrap your inputs in a <form> element:
function addFields() {
// Number of inputs to create
var number = document.getElementById('member').value;
// Container <div> where dynamic content will be placed
var container = document.getElementById('container');
// Clear previous contents of the container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for (i = 0; i < number; i++) {
// Append a node with a random text
container.appendChild(document.createTextNode('Member ' + (i + 1) + ' '));
// Create an <input> element, set its type and name attributes
var input = document.createElement('input');
input.type = 'text';
input.name = 'member' + i;
container.appendChild(input);
// Append a line break
container.appendChild(document.createElement('br'));
}
}
<input type="text" id="member" name="member" value="">Number of Pins: (max. 48)<br>
Add Pinout Entries
<form action="/url/to/post/to" method="POST">
<div id="container"></div>
<input type="submit">
</form>
If you’d like the submit button to only appear after at least one input is visible, you could add it at to div#container at the end of addFields(). I’ll leave this as an exercise to the OP, since it’s not much different to how you’re adding the input fields.

How to save the values in existing input fields when adding a new one?

This is what my program's body looks like:
<form id = "input">
<input id = "0" >
</form>
<p onclick = "add()"> Add Another</p>
And on clicking the above The following function is executed:
var inputArea = document.getElementById("input");
next = 1;
function add(){
inputArea.innerHTML+= " <input id = " + next+ ">" ;
Where next is the id of new input field. In this case, since 0 already exists so value of next is 1.
One problem that I am encountering with this is that after adding a new input field, the values in all existing input fields are lost. How to save these values? My attempt is to place this code in function add():
for (i=0;i<next;i++)
{inputs[i] = document.getElementById(i);
inputV[i]= inputs[i].value;
inputs[i].value = inputV[i];}
But this does not works..
var inputArea = document.getElementById("input");
next = 1;
function add(){
inputArea.innerHTML+= " <input id = " + next+ ">" ;
var inputs = new Array();
var inputV = new Array();
for (i=0;i<next;i++)
{inputs[i] = document.getElementById(i);
inputV[i]= inputs[i].value;
inputs[i].value = inputV[i];}
next++;
}
<form id = "input">
<input id = "0" >
</form>
<p onclick = "add()"> Add Another</p>
You may want to dynamically add elements to your DOM tree like so
function add() {
var form = document.getElementById("input");
var input = document.createElement("input");
form.appendChild(input);
}
The problem with what you're doing is that when you write inside an input field, the changes are not represented in the HTML code, only in the memory of the browser. Thus if you add text through to code to form.innerHTML, the browser is going to reinterpret the text inside the form which will be
<input id="0"> <input id="1"> ...
and this will result in two empty input of type text being displayed.
Edit: you can then add your id tag via
function add() {
var form = document.getElementById("input");
var input = document.createElement("input");
input.id = someValue;
form.appendChild(input);
}
N.B. please indent your code in a somewhat logical manner.
The reason this is happening is that the dom, or more specifically inputArea's innerHtml doesnt get changed when you type into a form field. And what youre doing is resetting the innerHTML with a blank input BEFORE youre capturing the values.
so whats going on is you have HTML like this:
<input id='0' />
then type into the form so that it behaves like:
<input id='0' value='foo' />
but thats not what the innerHTML actual is. its still <input id='0' /> because the value is kept in memory not on the dom.
if you want to add new elements to the form, you need to use appendChild instead
so convert
inputArea.innerHTML+= " <input id = " + next+ ">"
to
inputArea.appendChild(document.createElement('input'))

Dynamically adding HTML form fields based on a number specified by the user [duplicate]

This question already has answers here:
Dynamically creating a specific number of input form elements
(2 answers)
Closed 1 year ago.
I've a form field named Number of messages, and based on what number the user specifies, I want the exact number of text fields to be dynamically generated below to allow users to enter specified number of messages.
I have browsed through some examples where JQuery is used to generate dynamic form fields, but since I'm not acquainted with JQuery, those examples are a bit too complex for me to grasp. I do know the basics of JavaScript, and would really appreciate if I could find a solution to my query using JavaScript.
function addinputFields(){
var number = document.getElementById("member").value;
for (i=0;i<number;i++){
var input = document.createElement("input");
input.type = "text";
container.appendChild(input);
container.appendChild(document.createElement("br"));
}
}
and html code will be
Number of members:<input type="text" id="member" name="member" value=""><br />
<button id="btn" onclick="addinputFields()">Button</button>
<div id="container"/>
fiddle here
You can try something similar to this...
var wrapper_div = document.getElementById('input_set');
var btn = document.getElementById('btn');
btn.addEventListener('click', function() {
var n = document.getElementById("no_of_fields").value;
var fieldset = document.createElement('div'),
newInput;
for (var k = 0; k < n; k++) {
newInput = document.createElement('input');
newInput.value = '';
newInput.type = 'text';
newInput.placeholder = "Textfield no. " + k;
fieldset.appendChild(newInput);
fieldset.appendChild(document.createElement('br'));
}
wrapper_div.insertBefore(fieldset, this);
}, false);
No. of textfields :
<input id="no_of_fields" type="text" />
<div id="input_set">
<p>
<label for="my_input"></label>
</p>
<button id="btn" href="#">Add</button>
</div>
It is a simple task which is made simpler with jQuery. You need to first get the value from the input field for which you can use .val() or .value. Once you get the value, check if it is an integer. Now, simply use .append() function to dynamically add the elements.
HTML
<form id="myForm">
Number of Messages: <input id="msgs" type="text"> </input>
<div id="addmsg">
</div>
</form>
JAVASCRIPT
$("#msgs").on('change', function()
{
var num = this.value;
if(Math.floor(num) == num && $.isNumeric(num))
{
$("#addmsg").text('');
for(var i = 0; i < num; i++)
{
$("#addmsg").append("<input type='text'/><br/>");
}
}
});
Fiddle
Note, everytime the value in the input changes, I am first clearing the div by:
$("#addmsg").text('');
And then I loop and keep adding the input field. I hope this helps!

Javascript getElementsByName() for changing names

I have a automatically rendered HTML form which uses a index for the input fields.
for quantity:
<input id="id_orderline_set-0-orderline_quantity" name="orderline_set-0-orderline_quantity" onkeyup="orderlineTotal()" type="number" value="120">
for product price;
<input id="id_orderline_set-0-orderline_product_price" name="orderline_set-0-orderline_product_price" onkeyup="orderlineTotal()" type="number" value="22">
for total line price;
<input id="id_orderline_set-0-orderline_total_price" name="orderline_set-0-orderline_total_price" tag="orderline_total_price" type="number" value="2640">
For the following lines the index of the id and name are increased, only quantity example shown;
<input id="id_orderline_set-1-orderline_quantity" name="orderline_set-1-orderline_quantity" onkeyup="orderlineTotal()" type="number" value="55">
I would like to use the following JavaScript to calculate the total line price;
function orderlineTotal()
{
var orderlineTotalPrice = 0;
var theForm = document.forms["orderform"];
var orderlineQuantityField = theForm.getElementsByName["orderline_quantity"];
var orderlineProductPriceField = theForm.getElementsByName["orderline_product_price"];
var orderlineTotalPriceField = theForm.getElementsByName["orderline_total_price"];
for (var i = 0; i < orderlineQuantityField.length; i ++) {
orderlineTotalPrice = orderlineQuantityField[i].value * orderlineProductPriceField[i].value;
orderlineTotalPriceField[i].value = orderlineTotalPrice;
}
}
Offcourse this wont work because the name of the elements do not match. Can i lookup the name of the element by using a partial name? If not, how should i loop through the input boxes to calculate the line total?
You tagged jQuery so if you want to use jQuery you can use ends with selector:
$("input[name$='orderline_quantity']")
ends with
there's also
starts with
$("input[name^='id_orderline_set-0']")
and contains
$("input[name*='orderline_']")
Maybe you could use static names. Set the equal input names for inputs of the same type and then use this function:
var elements = document.getElementsByName('name');
for (var i=0; i<elements.length; i++) {
doSomething(elements[i]);
}
where name matches name of input.
Example
Instead of:
name="orderline_set-0-orderline_total_price"
use:
name="orderline_total_price"
and then:
var orderlineTotalPriceField = theForm.getElementsByName["orderline_total_price"];
and so on...

Categories

Resources