How to call svelte:component current component method?

Viewed 3429

I have this basic app, with some components that have a public load method. On some actions, I'd like to call that method on the current svelte:component, but I have no idea how to get a reference to the component instance. How can one do that?

    <script>
        import router from 'page'
        import Wines from './pages/Wines.svelte'
        import Entry from './pages/Entry.svelte'
        import TitleBar from './components/TitleBar.svelte'

        let page,
            params

        router('/', () => page = Wines)
        router('/wines', () => page = Wines)
        router('/entry/:id?', (ctx, next) => {
            params = ctx.params
            next()
        }, () => page = Entry)

        async function forceSync(){
            // how to call current component instance?
        }

    </script>

    <main>
        <TitleBar on:sync-request={forceSync}></TitleBar>
        <svelte:component this={page} params={params}/>
    </main>
2 Answers

You can use bind:this to get a reference to the current component and assign it to a variable. This also works for components rendered with <svelte:component> so you would organize you code similar to:

<script>
  import Child from './Child.svelte'

  let cmp

  const func = () => {
    // use cmp here: cmp.load()
  }
</script>

<svelte:component this="{Child}" bind:this="{cmp}" />

I'm pretty sure that we can't access functions on the component scripts. I didn't find any hint on the API and couldn't find any of the methods via devTools.

See the edit below

But we can send functions via custom events and you could solve your requirement like this:

App.svelte

<script>
    import A from './A.svelte'
    const syncMethods = []

    function sync() {
        syncMethods.forEach(f => f());
    }

    function storeSyncHandler(event) {
        syncMethods.push(event.detail);
    }
</script>

<button on:click={sync}>Sync Components</button>
<A on:mounted={storeSyncHandler}/>

A.svelte

<script>
    import { createEventDispatcher, onMount} from 'svelte';
    const dispatch = createEventDispatcher();

    let synced = ''

    function sync() {
        synced = '[SYNCED]';
    }

    onMount(() => {
        dispatch('mounted', sync)
    })
</script>

<div>Syncable Component {synced}</div>

The child component sends a 'mounted' event with it's 'sync' method. The parent stores that and can call it when ever needed. Hope it helps or gives some ideas.

Here's the REPL: https://svelte.dev/repl/6bc923a8326643cca79a6a2f8ee0ffe0?version=3.22.3

Edit:

It works like a charm when we export the function on the other component.

Here's the working REPL to call methods on mounted components:

https://svelte.dev/repl/8ba4270a9e334f35a591cdbfbac70e8e?version=3.22.3

Related