I think I am missing something in my fundamental understanding of creating dynamic HTML elements with javascript. After trying many of the examples I have found online to similar issues I have decided to post my question. I have a JS function which dynamically creates three input forms but I want to label each of the input boxes.
function newItem(){
instance++;
var oldInput = document.getElementById("itemInfo");
var parent = oldInput.parentNode;
var newDiv = document.createElement("div");
var item = document.createElement("INPUT");
var qty = document.createElement("INPUT");
var color = document.createElement("INPUT");
item.name = "item" + instance;
item.value = "Enter Item";
qty.name = "qty" + instance;
qty.value = "Enter Qty";
color.name = "color" + instance;
color.value = "Enter Color";
newDiv.appendChild(item);
newDiv.appendChild(qty);
newDiv.appendChild(color);
p = qty.parentNode;
var itemLabel = document.createElement("Label");
itemLabel.setAttribute("for", item);
itemLabel.innerHTML = "Item: ";
newDiv.insertBefore(itemLabel, item);
var qtyLabel = document.createElement("Label");
qtyLabel.setAttribute("for", qty);
qtyLabel.innerHTML = "Qty: ");
document.body.appendChild(qtyLabel, qty);
var colorLabel = document.createElement("Label");
colorLabel.setAttribute("for", color);
colorLabel.innerHTML = "Color: ");
color.appendChild(colorLabel);
parent.insertBefore(newDiv, oldInput);
}
If I comment out as follows I am able to correctly only the first input box:
var itemLabel = document.createElement("Label");
itemLabel.setAttribute("for", item);
itemLabel.innerHTML = "Item: ";
newDiv.insertBefore(itemLabel, item);
// var qtyLabel = document.createElement("Label");
// qtyLabel.setAttribute("for", qty);
// qtyLabel.innerHTML = "Qty: ");
// document.body.appendChild(qtyLabel, qty);
// var colorLabel = document.createElement("Label");
// colorLabel.setAttribute("for", color);
// colorLabel.innerHTML = "Color: ");
// color.appendChild(colorLabel);
However, if I uncomment either of the bottom two in an attempt to label the second and third input boxes, clicking the button with the newItem() function action does not create any additional input forms. How can I dynamically create the forms with their respective labels?
You have a syntax error on these lines:
qtyLabel.innerHTML = "Qty: ");
colorLabel.innerHTML = "Color: ");
Just alter to this:
qtyLabel.innerHTML = "Qty: ";
colorLabel.innerHTML = "Color: ";
Maybe because of this it works when you comment them.
Related
Add input per button click
function addInput() {
counter++;
// Create form inline div for product id
const div = document.createElement("div");
div.setAttribute('class', 'form-inline');
div.id = 'form-inline'+counter;
// Create column div for product id
const div1 = document.createElement("div");
div1.setAttribute('class', 'col-sm-3');
// Create form group div for product id
const div2 = document.createElement("div");
div2.setAttribute('class', 'form-group');
// Create label of Item ID for product id
const label = document.createElement("label");
label.htmlFor = 'ItemID' + counter;
label.innerHTML = "Item ID " + counter;
// Create input of Item ID for product id
const input = document.createElement("input");
input.id = 'ItemID' + counter;
input.type = 'text';
input.name = 'ItemID' + counter;
input.setAttribute('class', 'form-control');
input.placeholder = 'Enter product id';
// Create column div for product count
const div4 = document.createElement("div");
div4.setAttribute('class', 'col-sm-3');
div4.setAttribute('style', 'margin-left:10%;');
// Create form group div for product count
const div5 = document.createElement("div");
div5.setAttribute('class', 'form-group');
// Create label of Item Count for product id
const label2 = document.createElement("label");
label2.htmlFor = 'ItemCount' + counter;
label2.innerHTML = "Item Count " + counter;
// Create input of Item Count for product id
const input2 = document.createElement("input");
input2.id = 'ItemCount' + counter;
input2.type = 'text';
input2.name = 'ItemCount' + counter;
input2.setAttribute('class', 'form-control');
input2.placeholder = 'Enter product count';
// Append all items/divs
form.appendChild(div);
div.appendChild(div1);
div1.appendChild(div2);
div2.appendChild(label);
div2.appendChild(input);
div.appendChild(div4);
div4.appendChild(div5);
div5.appendChild(label2);
div5.appendChild(input2);
}
Remove input per button click
function removeInput() {
if (counter > 0) {
//document.getElementById("form-inline"+counter).remove();
//document.getElementById("form-inline"+counter).remove();
//document.getElementById("form-inline"+counter).removeChild(document.getElementById("form-inline"+counter).lastChild);
} else {
alert("error");
}
}
I basically want to be able to add as many inputs, and if needed to remove a couple, to remove them. at the end of the day you should be able to remove inputs until there are none left. The problem I'm having here is that the counter stops at the last added input and sets it to the last number so It will only remove the last input and I can't figure out how to go deeper than that. Thanks for any help.
//init function
function init() {
createTaskElements();
}
//create elements and add them to the unordered list
//set attributes
function createTaskElements() {
const arrChores = ["Walk the dog", "Set dinner table", "Load dishwasher", "Empy Dishwasher", "Clean dinner plates"];
for (var i = 0; i < arrChores.length; i++) {
var task = document.createElement("LI");
task.id = "task";
var input = document.createElement("INPUT");
input.type = "checkbox";
input.id = "chore";
var span = document.createElement("SPAN");
span.innerHTML = arrChores[i];
span.addEventListener("click", crossClick);
task.appendChild(input);
task.appendChild(span);
task.addEventListener("click", crossOut);
document.getElementById("itemsList").append(task);
}
}
//set the class name of the list item whenever it is clicked to completed
function crossOut() {
this.className = "completed";
}
function crossClick() {
}
W
hat I want to do when I click the span tag it checks the check box next to the element, but it isn't working.
I know the .checked method, but I'm not sure how I would get my function to work.
Replace
var span = document.createElement("SPAN");
span.innerHTML = arrChores[i];
with
const label = document.createElement("label");
label.textContent = arrChores[i];
label.htmlFor = input.id;
You don't need to add any Javascript behaviour to that label as it already comes with the functionality you ask for.
I'm trying to generate inputs automatically according to user's input.
For example if he enter 2 then it will automatically generate:
2 x (select option(values : M-Mr) + text input + text input + date
input )
I already made the 3 last inputs(text-text-date) , I faced a probleme with the select option
Thank you!!
<input type="text" id="member" name="member" value="">Number of members: <br/>
Fill Details
<div id="container"/>
and this is funtion :
function addFields(){
var number = document.getElementById("member").value;
var container = document.getElementById("container");
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for (i=0;i<number;i++){
container.appendChild(document.createTextNode("Member " + (i+1)));
var input = document.createElement("input");
var input1 = document.createElement("input");
var input2 = document.createElement("input");
input.type = "text";
input1.type = "text";
input2.type = "date";
container.appendChild(input);
container.appendChild(input1);
container.appendChild(input2);
container.appendChild(document.createElement("br"));
}
}
for the snipped code :
https://jsfiddle.net/f4hptzsy/
This example adds the select element with two options included.
See comments in the code for explanation of how it works.
// Identifies existing HTML elements
const member = document.getElementById("member");
const container = document.getElementById("container");
// Calls `useNumber` when `member` changes
member.addEventListener("change", useNumber);
// Defines `useNumber`
// (The listener can automatically access the triggering event)
function useNumber(event){
// The element where the event happened is the `target`
const memberValue = event.target.value;
// Calls `addFields` if the value can be used as an integer
const num = parseInt(memberValue);
if(num){
addFields(num);
}
}
function addFields(number) {
// Clears container
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
// Creates new elements and adds them to container
for (i = 0; i < number; i++) {
container.appendChild(document.createTextNode("Member " + (i + 1)));
// Defines a select element
const dropdown = document.createElement("select");
// Enumerates options and adds them to the select element
let options = ["M", "Mr"];
for (let option of options){
optionElement = document.createElement("option");
optionElement.value = option;
optionElement.innerHTML = option;
dropdown.appendChild(optionElement);
}
var input = document.createElement("input");
var input1 = document.createElement("input");
var input2 = document.createElement("input");
input.type = "text";
input1.type = "text";
input2.type = "date";
// Adds the select element to the page
container.appendChild(dropdown);
// Adds other inputs to the page
container.appendChild(input);
container.appendChild(input1);
container.appendChild(input2);
container.appendChild(document.createElement("br"));
}
}
<input id="member" />
<br />
<div id="container"></div>
EDIT:
The useNumber function just tests if the input is a valid integer before calling addFields.
It would be fine to omit this function and have addFields itself be the event listener instead, like:
// Identifies existing HTML elements
const member = document.getElementById("member");
const container = document.getElementById("container");
// Calls `addFields` when `member` changes
member.addEventListener("change", addFields);
function addFields(event) { // We name the triggering event "event"
// Gets value of element where the `change` event happened
const memberValue = event.target.value;
// Converts value to a number
const number = parseInt(memberValue);
// Makes sure conversion succeeded before proceding
if(number){
while (container.hasChildNodes()) {
container.removeChild(container.lastChild);
}
for (i = 0; i < number; i++) {
container.appendChild(document.createTextNode("Member " + (i + 1)));
// Defines a select element
const dropdown = document.createElement("select");
// Enumerates options and adds them to the select element
let options = ["M", "Mr"];
for (let option of options){
optionElement = document.createElement("option");
optionElement.value = option;
optionElement.innerHTML = option;
dropdown.appendChild(optionElement);
}
var input = document.createElement("input");
var input1 = document.createElement("input");
var input2 = document.createElement("input");
input.type = "text";
input1.type = "text";
input2.type = "date";
// Adds the select element to the page
container.appendChild(dropdown);
container.appendChild(input);
container.appendChild(input1);
container.appendChild(input2);
container.appendChild(document.createElement("br"));
}
}
}
<input id="member" />
<br />
<div id="container"></div>
The issue is the radio button didn't come up. And I am confused with the concept of create node, create node text, create node value, createElement, etc. those kind of concepts.
Here is my code, http://jsfiddle.net/vadjn2an/
Here is my function,
function displayQuestion() {
var question = document.getElementById("question");
question.textContent = questionPool[currentQuestion].question;
var numberOfChoices = questionPool[currentQuestion].choices.length;
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.appendChild(radio);
question.appendChild(label);
label.innerHTML = questionPool[currentQuestion].choices[i] + "<br>";
}
Thanks for your help in advance,
Try below code.
createTextNode
var questionPool = [
{
question: " Which is the biggest city in China?",
choices: ["Beijing", "Shanghai", "Guangzhou"],
correctAnswer: 1,
}
];
var question = document.getElementById("question");
var questionPool = questionPool[0];
question.textContent = questionPool.question;
for(var i=0;i<questionPool.choices.length;i++){
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', questionPool.choices[i]);
label.appendChild(radio);
var txt = document.createTextNode(questionPool.choices[i]);
label.appendChild(txt);
question.appendChild(label);
}
Here is the complete answer to your question. The HTML part
<form>
<label id="question">Question:</label><br />
<div id="answersBox">
</div>
<input type="button" value="save" />
</form>
The Javascript part
var questionPool = [
{
question: " Which is the biggest city in China?",
choices: ["Beijing", "Shanghai", "Guangzhou"],
correctAnswer: "Beijing",
}
];
var currentQuestion = questionPool[0].question;
document.getElementById('question').innerHTML = currentQuestion;
choiceList();
function choiceList() {
var question=questionPool[0];
for (choice in question.choices) {
var choiceSelection = document.createElement('input');
var choiceLabel = document.createElement('label');
choiceSelection.setAttribute('type', 'radio');
choiceSelection.setAttribute('name', 'choice');
choiceLabel.innerHTML=question.choices[choice];
choiceLabel.setAttribute('for', question.choices[choice]);
document.getElementById('answersBox').appendChild(choiceSelection);
document.getElementById('answersBox').appendChild(choiceLabel);
}
}
choiceList();
The reason it won't show up is because you replace label's innerHTML into
questionPool[currentQuestion].choices[i] + <br>.
when you append radio into label,label's innerHTML become "<input>...</input>"
but then you just replace it into
questionPool[currentQuestion].choices[i] + "<br>".
simple move the
label.innerHTML= ...
up before
label.appendChild can solve your situation.
here's a slightly modify answer without using innerHTML and outerHTML.
function displayQuestion() {
var question = document.getElementById("question"),
currentQuestion = 0,
numberOfChoices = questionPool[currentQuestion].choices.length;
question.textContent = questionPool[currentQuestion].question;
question.appendChild(document.createElement('br'));
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label'),
radio = document.createElement('input'),
textNode= document.createTextNode(questionPool[currentQuestion].choices[ i]),
lineBreakNode = document.createElement("br");
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.appendChild(radio);
label.appendChild(textNode);
label.appendChild(lineBreakNode);
question.appendChild(label);
}
}
http://jsfiddle.net/vadjn2an/9/
to have radio show before label, I use label.outerHTML to inject it as label's innerHTML
function displayQuestion() {
var question = document.getElementById("question");
var currentQuestion = 0;
var numberOfChoices = questionPool[currentQuestion].choices.length;
question.textContent = questionPool[currentQuestion].question;
question.appendChild(document.createElement('br'));
for(var i=0; i < numberOfChoices; i++) {
var label = document.createElement('label');
var radio = document.createElement('input');
radio.setAttribute('type', 'radio');
radio.setAttribute('name', 'choice');
radio.setAttribute('value', 'questionPool[currentQuestion].choices[i]');
label.innerHTML = radio.outerHTML + questionPool[currentQuestion].choices[i] + "<br/>";
question.appendChild(label);
}
}
http://jsfiddle.net/vadjn2an/8/
You need to append the radio button to question, please change the code line
from
label.appendChild(radio);
to
question.appendChild(radio);
Hope this helps!
I have a loop with changing parameters wich I'd like to use in a oninput function of the sliders I'm creating within that loop, but I can't get it to work. Here's a simplified version of my script:
for (var con in dict) {
var div = document.getElementById("content");
var conDiv = document.createElement("div");
conDiv.innerHTML = "<b>" + con + ":</b><br>";
var effectID = dict[con].effect_id;
for (var param in dict[con].params) {
var inp,span = document.createElement("span");
span.innerHTML = " " + param + " ";
conDiv.appendChild(span);
inp = document.createElement("input");
inp.type = "range";
inp.min = vars[effectID][param].min;
inp.max = vars[effectID][param].max;
inp.value = dict[con].params[param];
inp.oninput = function(con,param,val) {
setParam(con,param,val);
}(con,param,this.value);
conDiv.appendChild(inp);
}
div.appendChild(conDiv);
}
What's wrong with my code?
edit: My goal: I have a set of audio effects that I want to change. Every container (con) controls an effect node via multiple parameters. All those parameters have different min- and max-values and an actual value they have right now. Via the sliders I want to be able to call a function that changes the parameters of an container. Therefore, every slider should control one effect parameter.
That's because the callback is called after the loop finish, so your variables have changed.
A usual trick is to use an immediately called function whose scope can store your variable values :
for (var con in dict) {
(function(con) { // <= creates a scope and a new con variable
var div = document.getElementById("content");
var conDiv = document.createElement("div");
conDiv.innerHTML = "<b>" + con + ":</b><br>";
var effectID = dict[con].effect_id;
for (var param in dict[con].params) {
(function(param){
var inp,span = document.createElement("span");
span.innerHTML = " " + param + " ";
conDiv.appendChild(span);
inp = document.createElement("input");
inp.type = "range";
inp.min = vars[effectID][param].min;
inp.max = vars[effectID][param].max;
inp.value = dict[con].params[param];
inp.oninput = function() {
setParam(con,param,inp.value);
};
conDiv.appendChild(inp);
})(param);
}
div.appendChild(conDiv);
})(con);
}