Search code examples
classffireasonbucklescript

How to extend JavaScript HTMLElement class in ReasonML for web component?


For the following JavaScript code, how can I write it in ReasonML?

class HelloWorld extends HTMLElement {
  constructor() {
    super();
    // Attach a shadow root to the element.
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.innerHTML = `<p>hello world</p>`;
  }
}

I could not find any documentation on writing classes in ReasonML? I cannot use plain objects/types as I need to extend from HTMLElement class which doesn't work with ES style classes.

I have looked into this existing question - How to extend JS class in ReasonML however, it is a different thing. To write web component, we need to extend HTMLElement and must call it with new keyword. ES5 style extension mechanism doesn't work.


Solution

  • You can't. Not directly at least, since BuckleScript (which Reason uses to compile to JavaScript) targets ES5 and therefore has no knowledge of ES6 classes.

    Fortunately, ES6-classes require no special runtime support, but are implemented as just syntax sugar, which is why you can transpile ES6 to ES5 as shown in the question you link to. All you really have to do then, is to convert this transpiled output into ReasonML:

    var __extends = (this && this.__extends) || function (d, b) {
        for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
    var BaseElement = (function (_super) {
        __extends(BaseElement, _super);
        function BaseElement() {
            _super.call(this);
        }
        return BaseElement;
    }(HTMLElement));
    

    And depending on what specific class-features you actually need, you can probably simplify it a bit.