Javascript element object not referencing DOM Input element - javascript

I am creating an HTML input element in JS, then inserting it into the DOM. However, after it is inserted, the JS element object does not reference the new DOM element.
The element type button element and input type 'submit' work too, but the input element seems to not work with either 'number' or 'text,' which I would be using.
let parent = document.createElement('div');
let child = document.createElement('div');
let childInput = document.createElement('input');
childInput.type = 'text';
childInput.value = 'foobar';
child.append(childInput);
parent.append(child);
document.body.append(parent);
There are no errors, however in chrome dev tools I can see the JS element object is not tied to the DOM object for the input when type is set to text or number. The element IS inserted into the DOM, however it does not reflect the JS object reference, and the value is not inserted into the DOM element, nor would the class, id, etc.
Edit: Also, it does not work when using the appendChild function either.

It sounds like you are trying to change the HTML attributes by setting the JavaScript properties, which doesn't always work. You can use myElement.setAttribute(attributeName, newValue) to change the HTML attributes using JavaScript (and myElement.propertyName = newValue to change the JavaScript properties.)
Note that the initial value of the value attribute is reflected in the defaultValue property. (There are a few other oddball property names like this where reserved words in JS conflict with HTML terms.)
Note also that HTML attributes are case-insensitive, whereas JS properties are case-sensitive -- and kebab-case attributes get mapped to camelCase properties.
Much more info on this can be found here: https://javascript.info/dom-attributes-and-properties
let parent = document.createElement('div');
let child = document.createElement('div');
let childInput = document.createElement('input');
childInput.type = 'text';
childInput.id = 'initialId';
childInput.classList.add('someClass');
childInput.defaultValue = 'initial value';
child.append(childInput);
parent.append(child);
document.body.append(parent);
// Initial attributes
let insertedChild = document.getElementById('initialId');
console.log(insertedChild.outerHTML);
// Modified attributes
insertedChild.setAttribute('id', 'changedId');
console.log("`id` property (reflected from attribute): " + insertedChild.id);
insertedChild.setAttribute('value', 'changedValue');
console.log("`value` property (reflected from attribute): " + insertedChild.value);
console.log(insertedChild.outerHTML);

Related

trying to display value returns undefinded

HTML:
<span class="rbx-text-navbar-right text-header" id="nav-robux-amount">11</span>
CODE:
element = document.getElementById("nav-robux-amount")
if (element){
window.alert(element.value)
}
window.alert shows that the value of element is undefined
The .value property only exists on inputs.
The 'element' isn't a constant variable.
If you want to get the content, you can do the following:
const element = document.getElementById("nav-robux-amount");
if (element) window.alert(element.textContent)
Note: innerHTML is not as good as textContent, as it is vulnerable to attacks.

In JavaScript: Why doesn't setting a standard attribute's DOM property to an empty string remove the attribute like Element.removeAttribute() does?

I've learned that it's generally best to use DOM properties to set, access, and modify attributes which has lead me to avoid using setAttribute() and getAttribute(). Is there a similar way to remove DOM attribute properties without using removeAttribute()?
Given this HTML code:
<div id=el></div>
And this JavaScript code:
let el = document.getElementById('el');
console.log(el.outerHTML); //<div id='el'></div>
console.log(el.align === ''); //true
el.align = 'center';
console.log(el.outerHTML); //<div id="el" align="center"></div>
el.align = '';
log(el.outerHTML); //<div id="el" align=""></div>
It appears that el.align is set to an empty string by default. Why does resetting el.align to an empty string after assigning a value to el.align not remove the align attribute from the el.outerHTML presentation? Is this method just as effective even so? Or will this cause issues that removeAttribute() won't?
You need to understand the difference between markup attributes and DOM properties. Attributes don't always directly align with with a property on the JavaScript object.
The mapping between IDL attribute (properties) and the corresponding content attribute (markup) depends on the definition of this Interface Definition Language.
Setting some IDL attributes to false or null will remove them, for instance the ones mapping to boolean attributes, whose simple presence signifies a truthy value:
console.log(aud.loop);
console.log(aud.outerHTML);
aud.loop = false;
console.log(aud.outerHTML);
<audio id='aud' loop></audio>
However, some others like keywords attributes won't get removed, because the value you did set even if not part of the list of valid keywords will map to an invalid default value, for instance HTMLInputElement's type IDL will default to "text", if you set an invalid value, but the markup will still show this invalid value. (Your align attribute was part of this category, before it's been deprecated).
console.log(inp.type); // "number"
inp.type = "foobar"; // invalid
console.log(inp.type); // => default to "text
console.log(inp.outerHTML); // markup: "foobar"
inp.type = null; // invalid
console.log(inp.type); // => default to "text
console.log(inp.outerHTML); // markup: "null"
<input id="inp" type="number">
This makes sense since even though the browser doesn't recognize the set value as being one they support, it could very well be one that will be supported in the future.
The only way to remove such attributes is then to use Element.removeAttribute() method.
Same goes for other attributes which will accept any string as a valid value, for instance class (that is for HTML, CSS have stricter rules), here setting the IDL to any value will coerce it to a string, which will map to a valid in value in the IDL className.
console.log(el.className); // ""
el.className = null; // coerced to string
console.log(el.className); // "null"
console.log(el.outerHTML); // markup: "null"
el.className = false; // coerced to string
console.log(el.className); // "false"
console.log(el.outerHTML); // markup: "false"
el.className = ""; // ""
console.log(el.className); // ""
console.log(el.outerHTML); // markup: ""
<div id="el"></div>
And some will have different default values whether the attribute is missing, or in an invalid state, making their relation with the IDL even more obscure.
// crossOrigin IDL when no set is `null`.
console.log(img.crossOrigin);// attribute unset => IDL `null`
img.crossOrigin = 'use-credentials' // only non default valid value.
console.log(img.crossOrigin);
console.log(img.outerHTML);
img.crossOrigin = false; // invalid
console.log(img.crossOrigin); // IDL defaults to "anonymous"
console.log(img.outerHTML); // markup is `"false"`
img.crossOrigin = null; // remove
console.log(img.crossOrigin);
console.log(img.outerHTML);
<img id="img">
Finally some won't get reflected at all in the content attribute, like the HTMLInputElement.value.
inp.value = "new value";
console.log(inp.outerHTML);
<input id="inp" value="initialValue">
So you'd need to search for the definition of any IDL attribute to be sure how it should behave.

setAttribute() doesn't "remember" the value assigned to it's ID in a function if its a defined variable?

This function creates a unique label and corresponding delete button on the screen that, when pressed, deletes itself and the label by its unique ID. In order to be able to distinguish itself from other label-delete pairs it is assigned a unique ID based on the selection that caused its existence (from a select menu).
function saveSelection(selection) {
var element = document.getElementById("div1");
var del = document.createElement("button");
del.type = "button";
del.id = selection;
del.setAttribute("onclick", "deleteSelection(selection)");
del.appendChild(document.createTextNode("delete"));
element.appendChild(del);
}
function deleteSelection(selection) {
var element = document.getElementById("div1");
element.removeChild(document.getElementById(selection));
console.log("deleted");
}
The problem is, when I assign the selection to the buttons ID I have to refer to it by its variable name (actually called 'selection' in the function). When the delete button is pressed I suspect the code looks at the value passed in the onclick function and just sees 'selection' because it has "forgotten" what "selection" was, thus causing an error. Either this or I am not using proper syntax (lack/presence of ' or " quotes) and am thus passing/assigning it incorrectly.
Google Chrome's error console points out this line as the problem:
del.setAttribute("onclick", "deleteSelection(selection)");
specifially citing the 'selection' variable as being not defined in
deleteSelection(selection)
selection is not a global variable - presumably, it's scoped to the function that creates the element. Inline handlers that reference variables can only reference global variables.
But inline handlers are terrible practice anyway, they're basically eval inside HTML markup - better to attach the handler properly with Javascript instead, and no need for any ids:
document.querySelector('#add').onclick = function saveSelection() {
var element = document.getElementById("div1");
var del = document.createElement("button");
del.type = "button";
del.onclick = del.remove;
del.textContent = 'delete';
element.appendChild(del);
};
<div id="add">add</div>
<div id="div1"></div>

Dynamically change the type of a DOM element [duplicate]

Consider the following code:
var element = document.CreateElement("div");
element.toString(); // [object HTMLDivElement]
var element = document.CreateElement("somerandomtag");
element.toString(); // [object HTMLUnknownElement]
My gut instinct is that once an element has been created, it is essentially "strongly typed" (if such a thing exists in JavaScript), because "div" creates a HTMLDivElement and "somerandomtag" creates a HTMLUnknownElement, thus, the tag cannot be changed, because the created object corresponds directly to that tag.
Consider the following code:
var element = document.CreateElement("div");
element.toString(); // [object HTMLDivElement]
element.nodeName = "span"; // Doesn't work.
element.tagName = "span"; // Doesn't work.
So, is it possible to change an element from one type (e.g. "div") to another type (e.g. "span") beyond the object's creation?
EDIT: Please note...MUST be done with pure javascript...NO jQuery or other libraries/apis
An element's tagName is readonly (immutable) no matter what the element is. You cannot change an element's tag name without some rebuilding of the DOM. That is it's not possible to change an existing element, but it's not that difficult to create a new element and append the existing element's children.
var node = document.querySelector('div'),
newNode = document.createElement('span'),
parent = node.parentNode,
children = node.childNodes;
Array.prototype.forEach.call(children, function (elem) {
newNode.appendChild(elem);
});
parent.replaceChild(newNode, node);
http://jsfiddle.net/ExplosionPIlls/wwhKp/

What is the difference between these two ways to create an element?

var a = document.createElement('div');
a.id = "myDiv";
and
var a = document.createElement('div').id = "myDiv";
What is the difference between them such that the first one works and the second one doesn't?
Setting the id of the element does not return the element. It returns "myDiv" actually, so the var a is getting set to "myDiv" instead of the div itself.
The second one doesn't work because the "return" value from createElement is used to set the id. As that's an assignment and not chaining, it doesn't return the reference to the new element back to "a" and thus fails.
The second doesn't work as you're creating an element but immediately performing an operation upon it. The a variable is set to the string "myDiv" instead.
foo = 'bar' as a statement actually returns a value, which is 'bar'.
a = document.createElement('div'); //this sets `a` to DOM Node
a = document.createElement('div').id = 'myDiv'; //this sets `a` to 'myDiv'
//it's the same as
document.createElement('div').id = 'myDiv';
a = 'myDiv';
Don't ever do this
If you wanted to set both the ID and the a variable in one line, you could use parens:
(a = document.createElement('div')).id = 'myDiv';
That's because a = document.createElement('div') retuns the newly created DOM Node.
If you really want a short way, you can write :
(window.a=document.createElement('div')).id="myDiv";
Fiddle : http://jsfiddle.net/F23cD/
In the first statement you put the created element of type "div" into variable "a", and then set the element property "id" of "a" to "myDiv". Then "a" is now the element.
In the second statement you:
create the element of type "div": document.createElement('div')
set the element property "id" to "myDiv" and
set "a" to "myDiv" also
Then, "a" is now "myDiv" and not the element.
// use this
a.setAttribute("id","myDiv");

Categories