1

I created a node package for a Custom Element that I want to use in Angular and React. Therefor, in this library, I do not want specific Angular of React code.

My custom element is extending a button:

customElements.define('fancy-button', FancyButton, {extends: 'button'});

And this is how I use it:

<button is="fancy-button">Click me</button>  

This all works fine.

Until I try to use my custom element in a Angular component, then it suddenly behaves as a regular button. This answer is using a wrapper div, but I don't want that. Like the answer says: somehow (probably) Angular is first creating the button element, and afterwards is adding the is="fancy-button", which doesn't upgrade the button element to my FancyButton.

I want users of the library able to use the button in their html (<button is="fancy-button">Click me</button>), not force them to use javascript to generate this button.

The answer was in times of Angular 6, maybe there is a solution by now?

2
  • web components require a wrapper package to work with angular like angular-elements Commented Nov 5, 2024 at 6:47
  • FYI, extends:"button" (Customized Built-In Elements) will never be supported in Safari. Apple came up with valid arguments this part of Googles implementation has flaws. extends HTMLElement (Autonomous Elements) works in every browser Commented Nov 5, 2024 at 9:39

2 Answers 2

1

The is= and extending existing elements was an early part of the web components spec that was dropped. Some bits of it will work some of the time in some browsers, but you're best off not using it.

There seem to be a lot of old answers on here telling you to use it, and so AI consistently seems to suggest it, but is= syntax is deprecated, do not use it!

For security reasons you should not be able to extend any built-in component. Web components can extend other user-defined classes, but not browser-owned ones.

So...

  • <button is="fancy-button">Click me</button> may be extended by your custom component in some browsers sometimes, for now, and will fall back to just <button> the rest of the time.

  • <fancy-button>Click me</fancy-button> will work consistently in all current browsers, but won't render until the module (loaded async) has run and customElements.define has been called.

You can check for whether your component has loaded with await customElements.whenDefined('fancy-button'), but a more common practice is to use a CSS :not(:defined) pseudo-class to render something for the component that hasn't loaded yet (or that's blocked by JS not loading).

You can get the JS overhead right down, but ultimately you need that customElements.define. If you want to have a fallback that works outside of JS then you can use the slotted content (like <fancy-button><button>fallback</button></fancy-button>) as unregistered web components just display whatever is inside them.

Sign up to request clarification or add additional context in comments.

2 Comments

Sometimes it indeed worked in Safari. Funny because I've read that they were the ones objecting to extending elements.
@BigJ it's hard to tell with Safari, they're a lot less open about what spec changes they're investigating. I suspect their issue with is= came out of a proof of concept hack on a version that at least partially supported it.
0

Have you checked out Angular elements?

Personally, I don't have any experience with it, but it seems like it could be relevant if you're creating Web Components in Angular.

1 Comment

It seems that could work, but I'd rather have a pure javascript solution so it isn't framework dependent.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.