I’m trying to make an HTML page which has the list of all the anime I watched and am about to watch. So, I was trying to make an <anime>
tag for convenience purpose. It has name
and time
attributes. Here is the code for the custom elements:
Expected output: □ □ One Piece (15 Days)
Running this is giving the following error: Uncaught DOMException: CustomElementRegistry.define: 'anime' is not a valid custom element name
I’ve researched about valid custom element names, and this satisfies all those rules:
- any letter/symbol except capital letters
- start with lower case letter
- hyphens for spaces to separate words (here the name is only one word though)
class Anime extends HTMLDivElement {
constructor() {
super();
let name = this.getAttribute("name");
let time = this.getAttribute("time");
let children = [document.createElement("input"), document.createElement("input"), document.createElement("span"), document.createElement("b")];
children[0].type = "checkbox";
children[1].type = "checkbox";
children[3].innerHTML = name;
children[2].append(children[3]);
children[2].append(` ${time}`);
this.append(children[0], children[1], children[2]);
}
}
customElements.define("anime", Anime);
<anime name="One Piece" time="15 Days">
2
Answers
Name of the custom element must start with a lowercase letter, contain a hyphen, and satisfy certain other rules listed in the in the specification’s definition of a valid name
Syntax
In HTML
You can’t do DOM operations in the constructor. As there might not be DOM.(eg when elements are defined before DOM is parsed)
Easily tested by executing a
document.createElement("a-element")
in the DEV console. (note: many "guru" developers get this wrong too, because they use the not requireddefer
/async
on their<script>
calls without understanding what it does)Long read: My DEV.to blog on the connectedCallback
Do DOM operations in the
connectedCallback
that’s the signal the element appeared in the DOMextend HTMLDIVElement
(or any existing Element) is called a Customized Built-In Element and will never be supported in the (Apple) Safari Browser.Stick to Autonomous Elements
extend HTMLElement
unless you only deliver to Chromium and FireFox.My StackOverflow post on this
An "empty"
constructor
is pointless, as a
class
by default "super" calls its parent (in this case the constructor in HTMLElement)Use a helper function
createElement
so props and Eventlisteners can easily be set and your code doesn’t look like a dropped spaghetti dish.Custom Elements (aka Web Components) must be closed with a closing tag
<a-element></a-element>
the defining
class
can be an anonymous class inside thedefine
function. You rarely want a Named class.HTH