I want to display a new input field with a new name everytime a button is clicked. how do I achieve that? I found solutions to adding the input but none mentions adding a new name to it.
HTML:
<a href="" onclick="addKeywordFields()">Add a keyword</a>
<div id="fieldContainer"></div>
Javascript:
function addKeywordFields() {
var mydiv = document.getElementById("fieldContainer");
mydiv.appendChild(document.createTextNode("<input type='text' name=''>"))
}
CodePudding user response:
You should not use document.createTextNode
to create an input. This will only create a text element with content specified inside it.
Instead you should create an input using document.createElement('input')
and specify its type and name.
Since you need a dynamic name, you have to integrate a dynamic name generation logic. Here I used (new Date()).toISOString()
since this will e unique each time. Instead you have to use your own logic.
Working Fiddle
function addKeywordFields() {
var mydiv = document.getElementById("fieldContainer");
const input = document.createElement('input');
input.type = 'text';
input.name = (new Date()).toISOString(); // Some dynamic name logic
mydiv.appendChild(input);
}
<a onclick="addKeywordFields()">Add a keyword</a>
<div id="fieldContainer"></div>
CodePudding user response:
There's a ton of DOM methods designed to create, destroy, move, etc. There's generally three ways to create a DOM element programmatically:
clone an element with
.cloneNode()
and.append()
parse a string that represents HTML (aka
htmlString
) use.insertAdjacentHTML()
instead of.innerHTML
create an element with
.createElement()
and.append()
Assigning attributes/properties to an element can be done initially with .setAttribute()
once an attribute has been assigned to an element, it is technically a property. This distinction between attribute and property is blurry because methods seem to work 100% as does assigning properties. jQuery is not so flexible in this instance, .attr()
and .prop()
have silently failed on me when I forget about attribute/property quirks.
I rarely use methods to assign attributes, properties are terse and simple to use, here's a few common ones:
obj.id = "ID", obj.className = "CLASS", obj.name = "NAME"❉,
obj.type = "TEXT", obj.dataset.* = "*"
❉This is the property you use to set/get name
attribute
I always add a
<form>
if there's multiple form controls. There are special features and terse syntax if you use interfaces like HTMLFormElement✤ and HTMLFormControlsCollection✼. Moreover having a<form>
you can use it to listen for events for everything within it❉ and also take advantage of special form events like "input", "change", "submit", etc.HTMLFormElement.elements
collects all form controls (listed below)
<button>
,<fieldset>
,<input>
,<object>
,<output>
,<select>
,<textarea>
.
From the.elements
property, any form control can be referenced by#id
or[name]
. If there is a group of form controls that share a[name]
they can be collected into a HTMLCollection.
References
Further details are commented in example below
// Reference the form (see HTMLFormElement)
const UI = document.forms.UI;
// Register form to click event
UI.addEventListener('click', makeInput);
// Define a counter outside of function
let dataID = 0;
// Pass Event Object
function makeInput(e) {
/*
"this" is the form
.elements property is a collection of all form controls
(see HTMLFormsCollection)
*/
const io = this.elements;
// Event.target points to the tag user clicked
const clk = e.target;
/*
This is the fieldset containing the inputs it's in bracket notation
instead of dot notation because it's a hyphenated property
*/
const grp = io['form-group'];
// This is the static input
const inp = io.data;
// if the clicked tag is a button...
if (clk.matches('button')) {
// ...increment the counter
dataID ;
/*
This switch() delegates what to do by the clicked button's [name].
Each case is a different way to create an element and assign a unique
[name] by concatenating the "data" with the current number of dataID
*/
switch (clk.name) {
case 'clone':
const copy = inp.cloneNode(true);
copy.name = 'data' dataID;
grp.append(copy);
break;
case 'html':
const htmlStr = `
<input name="data${dataID}">`;
grp.insertAdjacentHTML('beforeEnd', htmlStr);
break;
case 'create':
const tag = document.createElement('input');
tag.name = 'data' dataID;
grp.append(tag);
break;
default:
break;
}
}
};
form {
display: flex;
}
fieldset {
display: inline-flex;
flex-direction: column;
justify-content: flex-startd;
max-width: 90%;
}
input,
button {
display: inline-block;
width: 80px;
margin-bottom: 4px;
}
input {
width: 150px;
}
button {
cursor: pointer;
}
<form id='UI'>
<fieldset name='btn-group'>
<button name='clone' type='button'>Clone Node</button>
<button name='html' type='button'>Parse htnlString</button>
<button name='create' type='button'>Create Element</button>
</fieldset>
<fieldset name='form-group'>
<input name='data'>
</fieldset>
</form>