Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

custom element throws Failed to construct HTMLElement error #818

Closed
ospatil opened this issue Sep 5, 2017 · 7 comments
Closed

custom element throws Failed to construct HTMLElement error #818

ospatil opened this issue Sep 5, 2017 · 7 comments
Labels

Comments

@ospatil
Copy link

ospatil commented Sep 5, 2017

Problem statement

I'm trying to use a svelte custom element in an angular app through SystemJS but I'm getting following error -

Error in console
  Uncaught TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function.
    at new MyThing (:5000/svelte/bundle.js:208)
    at HTMLDocument.createElement (:1:1545)

Versions

Svelte - latest through degit (degit sveltejs/template my-app)
Browsers - Latest Chrome and Opera

Reproduction

https://github.com/ospatil/svelte-custom-elem-bug

Setup instructions are on the README.md of the repo.

Analysis

Basically, the error is being thrown from the following line in the generated bundle.js -
HTMLElement.call(this);

I googled and found a few SO links like this where people have faced the same error when working with polymer custom elements in an es5 application - https://stackoverflow.com/questions/39037489/extending-htmlelement-constructor-fails-when-webpack-was-used

I tried adding shim as suggested in the post above, but no luck. In fact it also broke other StencilJS based custom elements on the page.

I tried es, cjs and umd formats in rollup config, but that doesn't seem to have any positive effect.

Note - It's entirely possible that this could turn out to be incorrect usage on my part. I hope this issue then serves as an example of 'how not to use this feature' for others 😃.

@Rich-Harris
Copy link
Member

Yeah, this is one of the rough edges of web components. Basically a custom element must be a class that extends HTMLElement, and somewhere that class is getting compiled to an ES5 constructor function. I thought commenting out the buble plugin in your Rollup config might fix it, but it doesn't — I think SystemJS might be compiling it again with Babel.

@ospatil
Copy link
Author

ospatil commented Sep 5, 2017

I removed angular and SystemJS from the application, compiled to iife, added script tag to index.html pointing to the generated bundle.js used my-thing tag directly in the body. Still no luck. I get the same error.

I have pushed the changes to the reproduction repo.

@Rich-Harris
Copy link
Member

It looks like you still have the buble plugin enabled in your Rollup config — try commenting that out?

@ospatil
Copy link
Author

ospatil commented Sep 5, 2017

Commented it out - now I don't get the error but don't see the custom tag output either :). Let me debug it a bit and I'll come back. Thanks for such a prompt attention.

And I haven't mentioned it so far - thank you a ton for svelte and bringing in post-framework paradigm!

@ospatil
Copy link
Author

ospatil commented Sep 6, 2017

Alright, some more information - here are the changes I made -

  1. Commented out buble plugin.
  2. Changed the rollup config entry to entry: 'src/MyThing.html' and compiled.

Now the generated bundle.js properly exports the MyThing class that extends HTMLElement.

With these changes I don't get the exception anymore but the custom tag is not rendered at all.

The host application is a purely static html application that uses bundle.js through a script tag and directly uses the custom tag in body as shown -

<!DOCTYPE html>
<html>

  <head>
    <base href="." />
    <title>Svelte custom elements</title>
    <link rel="stylesheet" href="style.css" />
    <script src="./svelte/bundle.js"></script>
  </head>

  <body>
    <my-thing></my-thing>
  </body>

</html>

This application doesn't import anything from bundle.js as mentioned on #797 (comment) scenario as a standalone custom element in a non-Svelte app since it's a purely static html application.

From what I can see, it seems that the _mount function is simply not getting called in the above usage scenario and therefore the custom tag is not rendered at all.

customElements.define('my-thing', MyThing);
assign( MyThing.prototype, proto , {
  _mount(target, anchor) {
    this._fragment.mount(this.shadowRoot, null);
    target.insertBefore(this, anchor);
  },
	
  _unmount() {
    this.parentNode.removeChild(this);
  }
});

return MyThing;

@Rich-Harris
Copy link
Member

Sorry for the delayed follow-up — I think this is the same as #821. Could you try installing the latest version of Svelte and seeing if it's fixed please?

@ospatil
Copy link
Author

ospatil commented Sep 13, 2017

It worked like a charm.

I haven't used anything as simple and clean as Svelte in a long time after years of framework fatigue. Thank you for that :).

@ospatil ospatil closed this as completed Sep 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants