Custom HTML element extending another custom element
Asked Answered
P

2

7

I have a custom HTML tag <fancy-foo> that I would like to extend the functionality of. Some of the <fancy-foo> elements would be extended using the pretty-bar custom element, so that I can use them in my HTML as

<fancy-foo is="pretty-bar">
    <!-- content -->
</fancy-foo>

so, I define classes FancyFoo and PrettyBar, define the fancy-foo element and extend it using pretty-bar, like so:

class FancyFoo extends HTMLElement {
  constructor() {
    super();
  }
}

class PrettyBar extends FancyFoo {
  constructor() {
    super();
  }
}

window.customElements.define('fancy-foo', FancyFoo);
window.customElements.define('pretty-bar', PrettyBar, {extends: 'fancy-foo'});

Sadly, Google Chrome spits out the error

Uncaught DOMException: Failed to execute 'define' on 'CustomElementRegistry': "fancy-foo" is a valid custom element name

That's an odd error. Strangely, it says "fancy-foo" is a valid custom element name; I know that, but why should that throw an error?

What's going on here?

Pneumoconiosis answered 2/8, 2019 at 18:50 Comment(0)
L
3

You cannot extend Custom Elements that way (with {extends: '...'}). You can only extend buit-in (= standard) HTML elements.

If you want to design PrettyBar as an extension of FancyFoo, you'll need to define it as an autonomous custom element:

class PrettyBar extends FancyFoo {...}
window.customElements.define('pretty-bar', PrettyBar)

Same thing for the HTML tag:

<pretty-bar></pretty-bar>
Lakieshalakin answered 2/8, 2019 at 21:3 Comment(5)
That makes sense. Still, the error message is oddly worded, but I guess that's irrelevant.Pneumoconiosis
I get "autonomous custom elements must extend HTMLElement" :(. Note that, in my case, FancyFoo is extending HTMLDivElement.Pestle
@Pestle but did you add {extends:'div'} as a third parameter?Lakieshalakin
Yes, with and without arises different exceptions. Apparently, it is not allowed to reextend an extension of a non-HTMLElement element class and implement it as a custom element. I don't understand why, and I need to read docs and docs to find that.Pestle
It's odd. If one can extend HTMLDivElement and implement it as a custom element, why can't I do the same with an extension of that class???Pestle
C
3

This way it is possible to create correct inheritance chain. Extended built-in element's class is further extensible:

class FancyFoo extends HTMLDivElement {
    constructor() {super();}
}

class PrettyBar extends FancyFoo {
    constructor() {super();}
}

window.customElements.define('fancy-foo', FancyFoo, {extends: 'div'});

window.customElements.define('pretty-bar', PrettyBar, {extends: 'div'});
<div is="fancy-foo"></div>
<div is="pretty-bar"></div>

customElements.define determines the is-name, constructor, and built-in's tag-name, if used this way. It does not need to know the exact constructor chain, provided it leads to the call of the appropriate built-in's constructor. You can establish the inheritance by extending one class by another.

Style it to override the div behavior, or use a more appropriate built-in element as base.

Cassiodorus answered 2/8, 2022 at 9:28 Comment(1)
Be careful because Safari MacOs and iOS don't support the is="" attribute unfortunatly even with the latest version (18) bugs.webkit.org/show_bug.cgi?id=182671Parkins

© 2022 - 2024 — McMap. All rights reserved.