Custom Element Illegal Constructor
Asked Answered
T

3

15

This code gives an "Illegal Constructor" Error, can anybody tell me why?

class MyCustomElement extends HTMLElement {
  constructor(){
    super();
    // Other things
  }
}

const myFunc = () => {
  const instance = new MyCustomElement();
  console.log(instance);
}

myFunc();
Tandem answered 19/5, 2020 at 0:7 Comment(1)
The funny thing with the same issue on my site is that I immediately call customElements.define() after defining its class - and much later the call to document.createElement() fails because of this exact error.Shawannashawl
T
18

After hours of searching I found that you MUST register the custom element BEFORE you can create an instance of it. I don't think this is in the spec, but this is the case for all browsers, also the error message sucks. I wish chrome would have just said "You must register a custom element before instantiating it" rather than "Illegal Constructor", which tells us almost nothing about what actually went wrong.

class MyCustomElement extends HTMLElement {
  constructor(){
    super();
    // Other things
  }
}

const myFunc = () => {
  const instance = new MyCustomElement();
  console.log(instance);
}

// Add this and it will start working
window.customElements.define('my-custom-element', MyCustomElement);

myFunc();
Tandem answered 19/5, 2020 at 4:41 Comment(4)
If you to new any built in HTMLElement, this error will be raised. Defining the custom element in the registry works around this somehow, but the error you observed is actually raised when the superclass constructor is newed.Damascus
Just want to know when we need this kind of custom element ?Bile
@SandeshSapkota This element is just an example for this question, it doesn't actually do anything. If your asking what custom elements are for you should probably google it, they are amazing.Tandem
Note (for completeness) that this behavior is specced here: html.spec.whatwg.org/#html-element-constructorsGrayish
P
3

Note that you can create a custom element before it is defined by using document.createElement().

This element will be created as an unknown element and then only upgrade to a custom element when defined.

class MyCustomElement extends HTMLElement {
  constructor(){
    super()
    console.log( 'created' )
  }
}

const myFunc = () => {
  const instance = document.createElement( 'my-custom-element' )
  console.log( instance )
  document.body.appendChild( instance )
}

myFunc()

customElements.define( 'my-custom-element', MyCustomElement )
Polliwog answered 19/5, 2020 at 17:18 Comment(3)
hi just wondering, do you think it's bad practice to use document.querySelector() to get another custom element inside of a custom element? example: Two web component /custom element inside of the normal document and inside of componentA, I use document.querySelector('componentB') to get componentB and do something with componentB, thanksFantasist
@Fantasist of course you can do it. Note that if they use ShadowDOM you'll have to get the shadowRoot reference before.Polliwog
including using this way to pass data? like this code example: #62373977Fantasist
B
1

It worked for me when I added {extends: 'div'} to the options which is the third parameter to the define method, so my code was like this

class MyCustomElement extends HTMLDivElement {
  constructor(){
    super()
  }

  connectedCallback() {
    console.log("Custom element added to page.");
  }
}

window.customElements.define('my-custom-element', MyCustomElement, {extends: 'div'})

// then I exported it and used it in another class
export default MyCustomElement;

and I used it like so

// another-file.js

import MyCustomElement from '../path/to/custom-element-class-file.js'

//...
const customDiv = new MyCustomElement()

document.body.append(customDiv)

//...

even the connectedCallback method was called after the element got added to the DOM

Bearing answered 9/4 at 20:28 Comment(1)
Great! I tried it with "button". But my <custome-button> became a regular <button>. So I'll be switching to extends HTMLElement. :)Buckle

© 2022 - 2024 — McMap. All rights reserved.