Skip to content

Properties of a custom element are not mapped before the registration is done #9487

@JohannesDoberer

Description

@JohannesDoberer

Describe the bug

When setting properties of an custom element instance by e.g. mySvelteWC.test = 'test value' before the registration in the customElementRegistry is finished, the props are not mapped to the internal svelte variables.

In such a case:

<svelte:options
    customElement={{
        tag: null,
        shadow: "none",
        props: {
            test: {
                reflect: false,
                type: "String",
                attribute: "testattribute",
            },
        },
        extend: (customElementConstructor) => {
            return class extends customElementConstructor {
                constructor() {
                    super();
                    this.attachShadow({ mode: "open", delegatesFocus: false });
                }
            };
        },
    }}
/>

<script lang="ts">
    import { onMount, onDestroy } from "svelte";
    export let test: string;
    let mainComponent: HTMLElement;

    onMount(async () => {
        const thisComponent: any = (mainComponent.getRootNode() as ShadowRoot)
            .host;

        console.log("thisComponent", thisComponent.test); //value -> 'test value'
        console.log("props", test); //value undefined
    });
    onDestroy(async () => {});
</script>

<div bind:this={mainComponent}>
    <span>Prop value: {test}</span>
</div>
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="module">
        import '/bundle.js';
    </script>
</head>

<body>
    <my-svelte-wc class="test"></my-svelte-wc>
    <script>
        //Working
        // customElements.whenDefined('my-svelte-wc').then(() => {
        //     let mySvelteWc = document.querySelector('.test');
        //     mySvelteWc.test = 'This is the workaround with "whenDefined"';
        // });

        //NOT working
        let mySvelteWc = document.querySelector('.test');
        mySvelteWc.test = 'test value';
    </script>
</body>

</html>

test is undefined (see console.log in onMount fn) but thisComponent.test has the correct value.

Reproduction

Here is a repo to reproduce the issue.
https://github.com/JohannesDoberer/sveltecustomelement

Logs

No response

System Info

Binaries:
  Node: 18.14.2 - ~/.nvm/versions/node/v18.14.2/bin/node
  npm: 9.5.0 - ~/.nvm/versions/node/v18.14.2/bin/npm
Browsers:
  Chrome: 119.0.6045.159
npmPackages:
  rollup: 2.78.0 => 2.78.0 
  svelte: ^4.2.3 => 4.2.3

Severity

annoyance

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions