0

I need to display the data entered into several text fields using div elements. There should be a dedicated div for each text input.

I have looked around all I have found is how to create dynamic inputs. But none of them explains how to use the created fields to read the info and display the info

I have updated the code to output two separate text fields but to have it display together is not working.

function display_array()
{
   var array=document.getElementsByClassName('tb');
   var e = "<hr/>";
var array2=document.getElementsByClassName('tb2');
  var e2 = "<hr/>";   
    
   for (var y=0; y<array.length; y++)
   {
     e += array[y].value ''+'' e2 += array2[y].value;
 // e2 += "Mac " + y + " = " + array2[y].value;
   }
document.getElementById("Result").innerHTML = e + 'm' + e2;
//document.getElementById("Result2").innerHTML = e;
}
//Counter to maintain number of textboxes and give them unique id for later reference
var intTextBox = 0;
var intTextBox2 = 0;
/**
* Function to add textbox element dynamically
* First we incrementing the counter and creating new div element with unique id
* Then adding new textbox element to this div and finally appending this div to main content.
*/
function addElement() {
    intTextBox++;
 intTextBox2++;
    var objNewDiv = document.createElement('div');
    objNewDiv.setAttribute('id', 'div_' + intTextBox);
    objNewDiv.innerHTML = 'Textbox ' + intTextBox + ': <input type="text" id="tb_' + intTextBox + '" class="tb" name="tb_' + intTextBox + '"/>';
    document.getElementById('content').appendChild(objNewDiv);
 
 
 var objNewDiv = document.createElement('div');
    objNewDiv.setAttribute('id', 'div_' + intTextBox);
    objNewDiv.innerHTML = 'Textbox1 ' + intTextBox + ': <input type="text" id="tb2_' + intTextBox + '" class="tb2" name="tb2_' + intTextBox + '"/>';
    document.getElementById('content').appendChild(objNewDiv);
}
<p>Demo of adding and removing textboxes dynamically using simple JavaScript</p>
<p>
    <a href="javascript:void(0);" onclick="addElement();">Add</a>
    <a href="javascript:void(0);" onclick="removeElement();">Remove</a>
</p>
<div id="content"></div><div id="content2"></div>


<input type="button" id="button2" value="Display" onclick="display_array();"></input>
<div id="Result"></div> 
Matt
  • 45
  • 1
  • 9
  • You should first correct your syntax error. – Scott Marcus Jan 26 '18 at 20:49
  • From the code you have shown array and array2 are undefined, there are no classes shown that have the class name of 'tb' or 'tb2', then you are not using array assignment properly see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array. Also to note those methods getElementby() return a collection, which is not remotely the same as an array. To create an array you have to use the spread operator [...nowyougetanarray] and can perform array operations – Matthew Lagerwey Jan 26 '18 at 21:55
  • @MatthewLagerwey A couple of corrections on your comment. The class `tb` is being assigned to the dynamically created text boxes. Collections *are* remotely the same as Arrays (not exactly the same, but certainly "array-like"). And, to create an array, you do not *have* to use the spread operator (which isn't even supported in many user agents) - `Array.prototype.slice.call(collection)` is recommended for now. – Scott Marcus Jan 26 '18 at 21:58
  • A couple of corrections to your correction considering that display array does not form a closure and is invoked nowhere that is visible within the code they are undefined! As for an object that has no methods attached to it being an array that is absurd. – Matthew Lagerwey Jan 26 '18 at 22:07
  • @MatthewLagerwey I have no idea what your last comment is even trying to say as my comment has nothing to do with that. You said: *Also to note those methods getElementby() return a collection, which is not remotely the same as an array.* and that is incorrect. Collections are "array-like" objects, so yes, they are "remotely" similar to Arrays. You then said: *To create an array you have to use the spread operator [...nowyougetanarray] and can perform array operations*. You do not ***have*** to use the spread operator as I've mentioned. My comment had nothing to do with closures. – Scott Marcus Jan 26 '18 at 22:17
  • https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection this is what it actually returns which has two methods one of which is read-only, while an actual array has around 30 methods attached to it, not only is it not an array but you can actually perform zero array methods on it, no you don't have to use the spread operator just declare an array empty array and fill it using one of the 30 array methods that are actually available to arrays. Strings are objects hold data and are objects, that must mean String === Array. – Matthew Lagerwey Jan 26 '18 at 22:28
  • @MatthewLagerwey Apparently, you aren't familiar with the term ["array-like object"](https://shifteleven.com/articles/2007/06/28/array-like-objects-in-javascript/) or [here](http://www.nfriedly.com/techblog/2009/06/advanced-javascript-objects-arrays-and-array-like-objects/) or [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice). It's not a matter of comparing method counts. Collections have a `length` property, indexes and are enumerable - that makes them more than *remotely* like an array and is why they can be converted to arrays so easily. – Scott Marcus Jan 26 '18 at 22:33
  • And, to you last point, a string is also an "array-like" object. I certainly never said "array-like" objects `===` Arrays. I was very careful to be clear about that. Lastly, it's OK to let yourself say "I don't know everything" rather than attack someone else who is trying to inform you about something you clearly aren't informed on. – Scott Marcus Jan 26 '18 at 22:35
  • It's kind of funny that the [link you posted](https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection) says this right at the top of the page: *The HTMLCollection interface represents a generic collection (**array-like object** similar to arguments) of elements (in document order) and offers methods and properties for selecting from the list.* – Scott Marcus Jan 26 '18 at 22:53

2 Answers2

1

The main issue is this:

e += array[y].value ''+'' e2 += array2[y].value;

which isn't a valid assignment statement and the source of your syntax error.

But, before we go into what it should be, your code needs to be cleaned up quite a bit. You have code that follows ancient practices that should no longer be used. For example, don't use hyperlinks with href=javascript:void() because you need something for the user to click on. Hyperlinks are for navigation, if you aren't doing navigation just use a button or just about any other element because just about everything supports a click event.

Another big thing to change is the way you are setting up your event handlers. You are using a technique that is 20+ years old. Don't use inline HTML event attributes (onclick, onchange, etc.) as there are many reasons that they can cause problems in your code. Instead, use .addEventListener() to register your event handlers.

Next, instead of making new elements by concatenating variables into strings, use the DOM API to create new elements as node objects, which makes configuring them much simpler and removes the need for concatenation.

While you certainly can loop over collections of elements with a counting for loop, the more modern and easy to use .forEach() method can be used on collections of nodes (in most, but not all browsers) and Arrays (in all modern browsers). What's great about .forEach() is that it will enumerate all the Array elements without you having to set up and manage a loop counter. This makes the code much simpler and avoids many common errors with loop counters.

<input> elements do not get a closing tag (</input>) and avoid using "self-terminated" tags (i.e. <hr/> as opposed to <hr>). That's an outdated syntax that gains you nothing.

Take note of how much cleaner the HTML and JavaScript are with the following code.

// Get all the DOM references your functions will need, just once, after the DOM is loaded
var add = document.getElementById("add");
var remove = document.getElementById("remove");
var result = document.getElementById("Result");
var btn = document.getElementById("btnDisplay");
var content = document.getElementById('content');
var textboxes = document.getElementsByClassName("tb");

// Set up event handlers:
add.addEventListener("click", addElement);
remove.addEventListener("click", removeElement);
btn.addEventListener("click", display_array);

function display_array() {
   var resultString = "";  // Final built up string will be stored here
   
   // Get all the textboxes into an array so .forEach() can safely be used
   Array.prototype.slice.call(textboxes).forEach(function(tb){
     resultString += "<hr>" + tb.value; // Just get value of textbox next to <hr>
   });
   result.innerHTML = resultString;  // Update the element with the results
}

var textBoxNum = 0;  //  Counter to track number of textboxes for id assignment

function addElement() {
  // Create and configure <div>
  var objNewDiv = document.createElement('div');
  objNewDiv.id = 'div_' + ++textBoxNum;
  objNewDiv.classList.add("row");
  
  // Create and configure <label>
  var lbl1 = document.createElement("label")
  lbl1.textContent = "Textbox " + textBoxNum;
  lbl1.for = "tb" + textBoxNum;

  // Create and configure <input type=text>
  var tb1 = document.createElement("input");
  tb1.type = "text";
  tb1.id = "tb" + textBoxNum;
  tb1.classList.add("tb");
  tb1.name = tb1.id;

  // Put labels and textboxes into the div
  objNewDiv.appendChild(lbl1);
  objNewDiv.appendChild(tb1); 
    
  // Put the div into the document
  content.appendChild(objNewDiv);
}

function removeElement(){

}
/* None of this is necessary, but it makes the spans look like buttons
   and add spacing to the end results. */
span.button {
  display:inline-block;
  border:1px solid gray;
  padding:4px;
  width:5em;
  background-color:#e0e0e0;
  text-align:center;
  cursor:pointer;
  user-select:none;
}

label {
  display:inline-block;
  padding-right:1em;
}

div.row {
  margin-bottom:.5em;
}
<p>Demo of adding and removing textboxes dynamically using simple JavaScript</p>
<p>
    <span id="add" class="button">Add</span>
    <span id="remove" class="button">Remove</span>
</p>
<div id="content"></div>
<div id="content2"></div>

<input type="button" id="btnDisplay" value="Display">
<div id="Result"></div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

I have corrected your code here in this line "e += array[y].value ''+'' e2 += array2[y].value;" and this should work for adding and displaying functionality

function display_array()
{
   var array=document.getElementsByClassName('tb');
   var e = "<hr/>";
var array2=document.getElementsByClassName('tb2');
  var e2 = "<hr/>";   
    
   for (var y=0; y<array.length; y++)
   {
     e += array[y].value + e2 + array2[y].value;
 // e2 += "Mac " + y + " = " + array2[y].value;
   }
document.getElementById("Result").innerHTML = e + 'm' + e2;
//document.getElementById("Result2").innerHTML = e;
}
//Counter to maintain number of textboxes and give them unique id for later reference
var intTextBox = 0;
var intTextBox2 = 0;
/**
* Function to add textbox element dynamically
* First we incrementing the counter and creating new div element with unique id
* Then adding new textbox element to this div and finally appending this div to main content.
*/
function addElement() {
    intTextBox++;
 intTextBox2++;
    var objNewDiv = document.createElement('div');
    objNewDiv.setAttribute('id', 'div_' + intTextBox);
    objNewDiv.innerHTML = 'Textbox ' + intTextBox + ': <input type="text" id="tb_' + intTextBox + '" class="tb" name="tb_' + intTextBox + '"/>';
    document.getElementById('content').appendChild(objNewDiv);
 
 
 var objNewDiv = document.createElement('div');
    objNewDiv.setAttribute('id', 'div_' + intTextBox);
    objNewDiv.innerHTML = 'Textbox1 ' + intTextBox + ': <input type="text" id="tb2_' + intTextBox + '" class="tb2" name="tb2_' + intTextBox + '"/>';
    document.getElementById('content').appendChild(objNewDiv);
}
<p>Demo of adding and removing textboxes dynamically using simple JavaScript</p>
<p>
    <a href="javascript:void(0);" onclick="addElement();">Add</a>
    <a href="javascript:void(0);" onclick="removeElement();">Remove</a>
</p>
<div id="content"></div><div id="content2"></div>


<input type="button" id="button2" value="Display" onclick="display_array();"></input>
<div id="Result"></div> 
Anilkumar
  • 42
  • 4
  • It will help other readers if you explain what OP did wrong and why your changes fix his problem – Andrew Lohr Jan 26 '18 at 21:29
  • I hope answer from [Scott Marcus](https://stackoverflow.com/users/695364/scott-marcus) answers your question. BTW I will it in mind and I will provide necessary explanation next onward – Anilkumar Jan 26 '18 at 23:29