Search code examples
javascriptecmascript-6importweb-component

Custom Element getter/setter not working when inside module


I have an issue with my custom element where I cannot make getter and setter work when inside a module.

<head>
    <script type="module">
        class Foo extends HTMLElement {
            get prop() {
                alert('get called')
                return 'somevalue'
            }

            set prop(value) {
                alert('set called');
                this._prop = value;
            }
        }
        customElements.define('foo-elem', Foo);
    </script>
</head>
<body>
    <foo-elem></foo-elem>
    <script>
        let foo = document.querySelector('foo-elem');
        foo.prop = 2; // <- this does not trigger the setter
    </script>
</body>

When I remove the type="module" from the script everything is working fine. Is there a way I can import (es6 imports) that way I declare every components in separate files ?


Solution

  • This is an issue related to the loading sequence of your scripts.

    Scripts with type=module are defer by default - meaning they are executed only when the document has finished parsing.

    Your other plain script tag is not defer so it executed when it's encountered - so it's executed first, before you've defined your custom element and its getters/setters. The module script is executed afterwards once the browser has got to the end of the document.

    defer scripts are however executed in the order they appear. So if you make the second script defer - either by adding the defer attribute, or by making it type="module" then the getters/setters will work as expected.