The following is the HTML that does what I want. It displays category: and beneath a value that I send in JavaScript.
<div id="category-order-id" class="additional-order-info">
<!-- <span class="additional-order-info-grey">category:</span>
Clothes -->
</div>
And here is my JavaScript
let orderCategory = document.getElementById("category-order-id");
orderCategory.textContent = `${order.category}`;
let categorySpan = document.createElement("span");
categorySpan.setAttribute("class", "additional-order-info-grey");
categorySpan.textContent = "category:";
orderCategory.appendChild(categorySpan);
What this code does, it that it first displays Clothes value that I send with JavaScript and beneath it display category.
Why I am creating a span element here is because if I set textContent of orderCategory it wil not display the span at all.
What am I doing wrong here?
textContent property replaces all the content in the element. If you want to keep order.category and "category:" as content, you need to use the appendChild function:
let orderCategory = document.getElementById("category-order-id");
const catTextContent = document.createElement("span");
catTextContent.textContent = order.category;
let categorySpan = document.createElement("span");
categorySpan.setAttribute("class", "additional-order-info-grey");
categorySpan.textContent = "category:";
orderCategory.appendChild(catTextContent);
orderCategory.appendChild(categorySpan);
Related
I am using vanilla javascript for my tiny weather project.
I have a problem with appending elements(which are created in run-time) in element.
Following HTML structure is my goal structure.
<div>
Min Temp <span class="small-font"> °C </span>
Max Temp <span class="small-font"> °C </span>
</div>
const div = document.createElement('div');
const span = document.createElement('span');
div.append("Min Temp", span, "Max Temp", span);
and my result is this:
<div>
Min Temp
Max Temp <span class="small-font"> °C </span>
</div>
I think the problem occurs when element.append() method get duplicated reference. But I can't find the docs explain about it. It's stack overflow at my brain!!!
Thanks for reading my question and have a nice day :)
It seems that the issue is that you are using the same span element for both occurrences of that span. If you want to have a separate span for each, you would most likely need to create 2 spans, 1 for each temperature.
Here is a code example you might be able to use:
const div = document.createElement('div');
const span1 = document.createElement('span');
const span2 = document.createElement('span');
div.append("Min Temp", span1, "Max Temp", span2);
Maybe if you want to sort the spans according to the div textContent (Min/ Max Temp) you could have a workaround with two individual divs like that:
const div1 = document.createElement("div");
div1.textContent = "Min Temp";
const span = document.createElement("span");
span.classList.add("small-font");
span.textContent = "C°";
div1.append("span");
const div2 = document.createElement("div");
div2.textContent = "Max Temp";
div2.append("span");
FYI: It is desirable that solutions be strictly vanilla Javascript.
How can I append an HTMLElement object to the middle of an element?
Here's a sample with a bit of what I mean.
const paragraph = document.createElement('p')
paragraph.innerHTML = 'Here is some text.<br><br>There is some text.'
document.body.appendChild(paragraph)
const wrappper = document.createElement('div')
const button = document.createElement('button')
button.onmouseup = () =>
{
// Do something
}
wrapper.appendChild(button)
Now imagine for a moment that I want to put the wrapper element inside of the paragraph element. But, not at the beginning or the end of it, but rather somewhere in the middle such as between the <br> tags. (But not necessarily after a tag) This can be done rather easily by taking the outerHTML of wrapper and inserting it into the paragraph's innerHTML via substrings, but this presents a problem. The resulting elements now in the flow of the html page are not the same as wrapper or button, which is evident when logging them, or when there is no onmouseup event being triggered.
So, ultimately, how do I put the exact HTMLElements referenced by the defined variables into the flow of the document in the middle of the contents of another element?
Find the <br> element and use insertAdjacentElement to insert after it.
const paragraph = document.createElement('p')
paragraph.innerHTML = 'Here is some text.<br><br>There is some text.'
document.body.appendChild(paragraph)
const wrappper = document.createElement('div')
const button = document.createElement('button')
button.innerText = 'Click';
const br = paragraph.querySelector("br");
br.insertAdjacentElement('afterend', button);
Maybe have a temporary <span> with a known id and then replace it with the element you wish to replaceWith would do...
const paragraph = document.createElement('p')
paragraph.innerHTML = 'Here is some text.<br><span id="destination"></span><br>There is some text.'
document.body.appendChild(paragraph)
const wrapper = document.createElement('div')
const button = document.createElement('button')
button.innerText = "here"
button.onmouseup = () =>
{
// Do something
}
wrapper.appendChild(button)
let destination = document.querySelector("#destination")
destination.replaceWith(wrapper)
I have a list with people's data inside it has a li element with 3 p tags inside, one for name, one for address and one for email.
I filled this list manually but due to some changes to my code I had to rewrite this so the html would be made with javascript.
My code looked like this
<p class="adres">#logopedist.Adres</p>
<p class="email">#logopedist.Email</p>
<p class="mobiel">#logopedist.Mobiel</p>
I rewrote this to build the html using javascript. This looks something like this.
var li = document.createElement('li');
li.className = "lijst";
li.id = "lijst";
li.onclick = "ficheVullen(this)";
p.className = "naam";
p.innerHTML = objLogos.Naam[i];
li.appendChild(p);
p.className = "adres";
p.innerHTML = objLogos.Adres[i];
li.appendChild(p);
var p = document.createElement('p');
p.className = "mobiel";
p.innerHTML = objLogos.Mobiel[i];
li.appendChild(p);
My list generates properly. But in my old code I had this at the start of the list.
<li class="lijst" onclick="ficheVullen(this)">
Whenever you would click an li element it would fill a div with the info from the p tags inside that li, so it would fill the div with name, address, mobile,etc
I cannot seem to get this function to work anymore. It only works on the very first LI element and only works for the name. Even though my code is the same and I append classes to the tags like it had in my old code.
The function looks like this:
function ficheVullen() {
FicheNaam = document.getElementById("FicheNaam");
FicheAdres = document.getElementById("FicheAdres");
FicheGSM = document.getElementById("FicheGSM");
FicheNaam.innerHTML = this.querySelector('.naam').textContent;
FicheGSM.innerHTML = this.querySelector('.mobiel').textContent;
FicheAdres.innerHTML = this.querySelector('.adres').textContent;
I get this error now. Cannot read property 'textContent' of null
I call this function here:
window.onload = function() {
changePage(1);
document.getElementById("lijst").addEventListener("click", ficheVullen);
};
The changepage function is part of my pagination where I use javascript to build the list.
When I move the eventlistener out of this I get this error: Cannot read property 'addEventListener' of null.
I hope this gives enough context
You have to use setAttribute to set id.
elm.setAttribute("id", "uniqueId");
Your case : li.setAttribute("id", "lijst")
li.id = "lijst"; will add "id" to object not as attribute
const parent = document.getElementById("container")
let elm = document.createElement("p")
elm.setAttribute("id", "pElm")
elm.innerText = "p tag"
parent.append(elm)
document.getElementById("pElm").style.background = "red"
<div id="container"></div>
I have 3 inputs that are nestled inside a span tag (I'm using span and not li because I have many li's in my code). I have a javascript function that appends each span tag (which includes the 3 inputs). I need each input to have a specific id name. Not sure how to do this, I'm learning javascript right now so forgive me for I'm a noob.
In my function I have the appendchild working for the span tag. At the bottom of the code I have a for loop that I wrote to append an ul/li and that name works. But I can't get that same functionality to work for the span tags.
How can I append child and each time I appendchild that the inputs get a new id name?
Here is my code so far:
function budgetList(){
var elmnt = document.getElementsByTagName("SPAN")[0];
var cln = elmnt.cloneNode(true);
var budgetListing = document.getElementById("budget-listing");
var append = budgetListing.appendChild(cln);
var expenseName = document.getElementById('expenseName');
var expectedExpense = document.getElementById('expectedExpense');
var actualExpense = document.getElementById('actualExpense');
var ul = document.createElement("ul");
document.body.appendChild(li);
for(var i = 0; i <= 0; i++){
var li = document.createElement("li");
li.className = "budget-list" + i;
var a = document.createElement("a");
a.innerHTML = "<input type='text'>";
// a.innerHTML = "Subfile " + i;
var att = document.createAttribute("class");
att.value = "budgeting" + i;
li.appendChild(a);
ul.appendChild(li);
}
}
Here is the html
<button onclick="budgetList()">Add New Row</button>
<input type="button" value="save" onclick="save()" />
<ul id="budget-listing">
<span>
<input type="text" id="expenseName">
<input type="text" id="expectedExpense">
<input type="text" id="actualExpense">
</span>
</ul>
A few things...
1) <ul> stands for Unordered List and <ul> elements expect their children to be <li> elements (which you can remember as List Item). So, while some browsers may be forgiving of you appending spans to your <ul> tag, it's not considered good practice. And is technically a violation of the standard
2) Your loop will only run exactly once. You'll see it's starting with variable i initialized at 0 and will only run as long as i<=0 which will only ever be true on the first iteration because afterwards you increment (i++) which means the second time through i will equal 1 and 1 is NOT less than or equal to 0. So, in this case there's no need to use a loop at all.
3) Your code is a little disjointed from what you requested and what the page context is suggesting. It appears to me, when the user clicks the button you want to duplicate the span with 3 inputs. If this is indeed the case, then I offer the following solution...
function budgetList(){
// You get the span that will serve as a template, good
var elmnt = document.getElementsByTagName("SPAN")[0];
// you clone it, good
var cln = elmnt.cloneNode(true);
//next we want to modify the IDs of the child spans.
// A good way to do this is to use a unique number that will change with every step
// There a few ways to get a unique number each time
// I propose taking the number of span groups
var budgetListing = document.getElementById("budget-listing");
var uniqueNumber = budgetListing.childNodes.length;
// Now we update all the ids using the unique number
cln.getElementsByTagName('INPUT')[0].setAttribute('id', "expenseName_"+uniqueNumber);
cln.getElementsByTagName('INPUT')[1].setAttribute('id', "expectedExpense_"+uniqueNumber);
cln.getElementsByTagName('INPUT')[2].setAttribute('id', "actualExpense_"+uniqueNumber);
// and write our new span group into the container
budgetListing.appendChild(cln);
}
Let me know if I made any incorrect assumptions or if this is close to what you're requesting. JavaScript and its interaction with HTML can be confusing at first, but stick with it!
EDIT: Didn't realize getElementById wasn't a function... Replaced with getElementsByTagName
For a little project I am doing I am interested in creating a small modal form using JavaScripts createElement function. I have the HTML laid out and have actually built the code in JS but sadly cannot seem to get everything to add correctly.
The HTML is supposed to look like this:
<div id="qtModal">
<div id="qtHead">
<span id="qtHeading">Quick Tools</span>
<span id="qtClose">X</span>
</div>
<table id="qtWrapper" border="1">
<tr>
<td id="qtRail">
<ul>
<li><a class="qtLink" href="#">Delete</a></li>
</ul>
</td>
</tr>
</table>
</div>
The JavaScript I set up to make this and append it to the body is as follows:
var qtModal = document.createElement("div");
qtModal.setAttribute("id", "qtModal");
var qtHead = document.createElement("qtHead");
qtHead.setAttribute("id", "qtHead");
var qtHeading = document.createElement("span");
qtHeading.setAttribute("id", "qtHeading");
qtHeading.textContent = "Quick Tools";
var qtClose = document.createElement("span");
qtClose.setAttribute("id", "qtClose");
qtClose.textContent = "X";
var qtWrapper = document.createElement("table");
qtWrapper.setAttribute("id", "qtWrapper");
qtWrapper.setAttribute("border", "1");
var qtTr = document.createElement("tr");
var qtRail = document.createElement("td");
qtRail.setAttribute("id", "qtRail");
var qtUl = document.createElement("ul");
var qtLi1 = document.createElement("li");
var qtA1 = document.createElement("a");
qtA1.setAttribute("class", "qtLink");
qtA1.setAttribute("href", "#");
//We want to build the modal head right here
qtHead = qtHead.appendChild(qtHeading);
qtHead = qtHead.appendChild(qtClose);
qtModal = qtModal.appendChild(qtHead); //Add to modal
//Build the table from the inner most element up to the top
qtLi1 = qtLi1.appendChild(qtA1);
qtUl = qtUl.appendChild(qtLi1);
qtRail = qtRail.appendChild(qtUl);
qtTr = qtTr.appendChild(qtUl);
qtWrapper = qtWrapper.appendChild(qtTr);
qtModal = qtModal.appendChild(qtWrapper); //Add to modal
$("body").append(qtModal); //Add to body
My logic is the we first want to add the heading and the close button to the head element by appending them one at a time. I will then append the head to the actual modal element. Next up I will start building the table from the innermost element (a) up to the outermost element (form) then append those to the Modal. When I use the code above only the innermost element (a) gets appended to the body. I would appreciate it if someone could help either point out what I am doing wrong (I might be misusing createElement or appendChild) or how I could fix it to generate the proper HTML structure listed above.
This is basically fine - the issue is that you're overwriting your existing nodes with your appended nodes. Here's why that's happening.
The appendChild(...) method returns the DOM element that was just appended. So, when you call qtHead = qtHead.appendChild(qtHeading), then
qtHeading gets appended to qtHead
qtHead.appendChild(qtHeading) returns a reference to qtHeading
qtHead gets overwritten with qtHeading
So, to fix this, just take this:
qtHead = qtHead.appendChild(qtHeading);
qtHead = qtHead.appendChild(qtClose);
qtModal = qtModal.appendChild(qtHead); //Add to modal
//Build the table from the inner most element up to the top
qtLi1 = qtLi1.appendChild(qtA1);
qtUl = qtUl.appendChild(qtLi1);
qtRail = qtRail.appendChild(qtUl);
qtTr = qtTr.appendChild(qtUl);
qtWrapper = qtWrapper.appendChild(qtTr);
qtModal = qtModal.appendChild(qtWrapper); //Add to modal
and rewrite it as this:
qtHead.appendChild(qtHeading);
qtHead.appendChild(qtClose);
qtModal.appendChild(qtHead); //Add to modal
//Build the table from the inner most element up to the top
qtLi1.appendChild(qtA1);
qtUl.appendChild(qtLi1);
qtRail.appendChild(qtUl);
qtTr.appendChild(qtUl);
qtWrapper.appendChild(qtTr);
qtModal.appendChild(qtWrapper); //Add to modal