5

Right now, if you follow the exact specifications of v1 of the custom elements spec, it's not possible to use custom elements in browsers that don't support classes.

Is there a way to create v1 custom elements without using the class syntax so that they are fully functional in Chrome, FireFox and IE11. Also, since IE11 doesn't have native support for custom elements, I'm assuming we will probably need to use some pollyfills, so what polyfills or libraries do we need in order to make this work in IE11?

I've messed around with Polymer 2, Polymer 3, and Stencil, but they are all a bit heavy-duty for some of the things we want to create.

This question seems to be on the right track, but I had some trouble getting it to work in IE11, so also how can I use Reflect.construct in IE11 for the purposes of custom elements?

Intervalia
  • 10,248
  • 2
  • 30
  • 60
TwitchBronBron
  • 2,783
  • 3
  • 21
  • 45
  • Possible duplicate of [How to inherit from the DOM element class](https://stackoverflow.com/questions/1489738/how-to-inherit-from-the-dom-element-class) –  May 11 '18 at 15:54
  • Possible duplicate of [Creating custom element without using class keyword](https://stackoverflow.com/questions/46071707/creating-custom-element-without-using-class-keyword) – Supersharp May 12 '18 at 14:52
  • or this one: https://stackoverflow.com/q/39831336/4600982 – Supersharp May 18 '18 at 12:57

1 Answers1

8

Here's a full example of writing ES5-compatible custom elements using the v1 spec (credit to this comment on github)

<html>

<head>
  <!--pollyfill Reflect for "older" browsers-->
  <script src="https://cdn.rawgit.com/paulmillr/es6-shim/master/es6-shim.min.js"></script>
  <!--pollyfill custom elements for "older" browsers-->
  <script src="https://cdn.rawgit.com/webcomponents/custom-elements/master/custom-elements.min.js"></script>
  <script type="text/javascript">
    function MyEl() {
      return Reflect.construct(HTMLElement, [], this.constructor);
    }

    MyEl.prototype = Object.create(HTMLElement.prototype);
    MyEl.prototype.constructor = MyEl;
    Object.setPrototypeOf(MyEl, HTMLElement);

    MyEl.prototype.connectedCallback = function() {
      this.innerHTML = 'Hello world';
    };
    customElements.define('my-el', MyEl);
  </script>
</head>

<body>
  <my-el></my-el>
</body>

</html>

Also, for the typescript lovers, here's a way to write custom elements using typescript that will still work when compiled to ES5.

<html>
<head>
    <!--pollyfill Reflect for "older" browsers-->
    <script src="https://cdn.rawgit.com/paulmillr/es6-shim/master/es6-shim.min.js"></script>
    <!--pollyfill custom elements for "older" browsers-->
    <script src="https://cdn.rawgit.com/webcomponents/custom-elements/master/custom-elements.min.js"></script>
    <script type="text/typescript">
        class MyEl extends HTMLElement{
          constructor(){
              return Reflect.construct(HTMLElement, [], this.constructor);
            }  
            
            connectedCallback () {
              this.innerHTML = 'Hello world';
          }
        }

        customElements.define('my-el', MyEl);
    </script>

</head>

<body>
    <my-el></my-el>
    <!-- include an in-browser typescript compiler just for this example -->
    <script src="https://rawgit.com/Microsoft/TypeScript/master/lib/typescriptServices.js"></script>
    <script src="https://rawgit.com/basarat/typescript-script/master/transpiler.js"></script>
</body>

</html>
TwitchBronBron
  • 2,783
  • 3
  • 21
  • 45
  • Much of your answer seems to be hidden behind libraries, so the actual solution isn't included here. How do I know this actually works in old, ES5 browsers? –  May 11 '18 at 15:42
  • Did you try in any implementation that didn't support the non-ES5-standard `__proto__`? IE11 is the first version that supports it. –  May 11 '18 at 15:48
  • I'm pretty sure that no polyfill will be able to emulate ES6 `Reflect.construct` for builtin constructors – Bergi May 11 '18 at 15:57
  • @CrazyTrain I had been trying to make the question generic, but your comments made me realize that I needed to be more specific about exactly what I was trying to accomplish. I updated my question to be more specific about the requirements. Thanks! – TwitchBronBron May 15 '18 at 12:09