Issue
I am working on a Vanilla JS Component and I am trying to use the innerHTML()
function to change the text in a certain ID in the render()
HTML code. However, I am getting the Cannot set properties of null (setting 'innerHTML')
error. I am confused why this error is arising because the ID of the element I am looking for does exist, and the type of the string I am planning to put intto the innerHTML()
function is a string and is not null type. The code is below
class checkoutitemC extends HTMLElement {
constructor() {
super();
}
connectedCallback(){
const itemName = this.getAttribute('name');
document.getElementById("nameX").innerHTML=`${itemName}`;
const price = this.getAttribute('price');
document.getElementById("priceX").innerHTML=`$${price}`;
const qty = this.getAttribute('qty');
document.getElementById("qtyX").innerHTML=`Qty: ${qty}`;
this.render()
}
render(){
this.innerHTML=`
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<h6 class="my-0" id="nameX"></h6>
<small class="text-muted" id="qtyX"></small>
</div>
<span class="text-muted" id="priceX"></span>
</li>
`
}
}
I tried checking the types of the inputs I was putting into the innerHTML Text and found that to not be null. I also tried simiplying the issue in a seperate HTML file where innerHTML()
and getElementById()
do work. This tells me that something with the structure of the component causes this issue.
What are some potential explanations for this weird behaviors?
Solution
Your connectedCallback
method needs to call the render()
method before it attempts to perform the calculations or set values for elements that do not, at that stage, exist.
class checkoutitemC extends HTMLElement {
constructor() {
super();
}
connectedCallback(){
this.render();
const itemName = this.getAttribute('name');
document.getElementById("nameX").innerHTML=`${itemName}`;
const price = this.getAttribute('price');
document.getElementById("priceX").innerHTML=`$${price}`;
const qty = this.getAttribute('qty');
document.getElementById("qtyX").innerHTML=`Qty: ${qty}`;
}
render(){
this.innerHTML=`
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<h6 class="my-0" id="nameX"></h6>
<small class="text-muted" id="qtyX"></small>
</div>
<span class="text-muted" id="priceX"></span>
</li>`
}
}
customElements.define( "checkout-item", checkoutitemC );
<checkout-item name="banana" price="123.45" qty="35"></checkout-item>
One thing to note with the approach you have chosen with using ID elements and document.getElementByID
is that you cannot create more than one of these custom items. If you use this.querySelector('#ID')
rather than document
it should allow multiple instances.
class checkoutitemC extends HTMLElement {
constructor() {
super();
}
connectedCallback(){
this.render();
const itemName = this.getAttribute('name');
this.querySelector("#nameX").innerHTML=`${itemName}`;
const price = this.getAttribute('price');
this.querySelector("#priceX").innerHTML=`$${price}`;
const qty = this.getAttribute('qty');
this.querySelector("#qtyX").innerHTML=`Qty: ${qty}`;
this.querySelector('output').textContent='Total: '+Math.abs(parseFloat(this.getAttribute('price')) * parseFloat( this.getAttribute('qty') ) ).toFixed(2);
}
render(){
this.innerHTML=`
<style>
li.list-group-item{ margin:1rem; padding:1rem; border:1px dotted grey; display:inline-block; }
output{ display:block; color:red; margin:1rem 0 }
</style>
<li class="list-group-item d-flex justify-content-between lh-condensed">
<div>
<h6 class="my-0" id="nameX"></h6>
<small class="text-muted" id="qtyX"></small>
</div>
<span class="text-muted" id="priceX"></span>
<output></output>
</li>`
}
}
customElements.define( "checkout-item", checkoutitemC );
<checkout-item name="banana" price="123.45" qty="35"></checkout-item>
<checkout-item name="apple" price="42.52" qty="15"></checkout-item>
Answered By - Professor Abronsius
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.