I am just starting with Svelte. I have a searchbar component and an unique instance of that component: main_searchbar. I want to focus that component from a different component.
So I export input in searchbar.svelte:
<script>
export let value = '';
export let input;
</script>
<span class="searchbar">
<input
class="search"
type="text"
name="search"
bind:value
bind:this={input}
>
</span>
Then I import it in main_searchbar.svelte:
<script context="module">
import Searchbar from './searchbar.svelte';
export let obj;
</script>
<Searchbar bind:this={obj}/>
Then I create a button to focus:
<script>
import {obj} from './main_searchbar.svelte';
function focus() {
obj.input.focus();
}
</script>
<button on:click={focus}>Focus</button>
And last the App.svelte:
<script>
import Main_searchbar from './main_searchbar.svelte'
import Focus from './focus.svelte'
</script>
<Main_searchbar/>
<Focus/>
Of course this doesnt work: https://svelte.dev/repl/c4eb67950c6240e593173431edb18e1a?version=3.38.2 What is the correct way of doing this in Svelte?
Svelte ships with stores , a pretty neat way to manage global state; with these, you don't have to pass references between components. Here's a simplified solution using a writable store:
store.js
import { writable } from 'svelte/store';
// An observable string value.
export const focused = writable('');
searchbar.svelte
<script>
import { focused } from './store'
export let target;
let input;
// When the value of the "focused" store is equal to target,
// call focus() on the input.
focused.subscribe((v) => {
if(v === target) {
input.focus()
// Because subscribe only notifies us of changes,
// we have to reset the store or the focus button
// will stop working.
focused.set('');
}
})
</script>
<span class="searchbar">
<input bind:this={input} />
</span>
focus.svelte
<script>
import { focused } from './store';
export let targeting;
// Use the .set() method to set the value of our `focused` store,
// triggering all our subscribers (like the one in searchbar.svelte).
const focus = () => focused.set(targeting)
</script>
<button on:click={focus}>Focus</button>
App.svelte
<script>
import Searchbar from './searchbar.svelte'
import Focus from './focus.svelte'
// target and targeting must match.
// This allows you to reuse the focus component!
</script>
<Searchbar target="search" />
<Focus targeting="search" />
To fix your problem you can add the following line to Searchbar.svelte
<svelte:options accessors/>
But something feels very "un-svelte" about your setup, if I were you I would reconsider the architecture.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.