Reputation: 71
I have two components that are very far away in the component tree and I have doubts about how to communicate between both. I have the search component, listItems and a store.
store.svelte
<script context="module" lang="ts">
import type {Items} from '../../Models/Items.model';
import { writable } from 'svelte/store';
export const dataItems = writable<Items[]>([]);
const filterInfo = (term:string) => {
dataItems.update(item => {
item.filter(x => {
return x.name.toLowerCase().includes(term.toLowerCase())
|| x.description.toLowerCase().includes(term.toLowerCase());
})
return dataItems;
})
}*/
export const dispatcher = {filterInfo};
</script>
search component
<script lang="ts">
import { dispatcher } from './ViewI/store.svelte';
let value:any;
const handleChange = () => {
dispatcher.filterInfo(value)
console.log(value)
}
</script>
<Search>
<input bind:value
on:input={handleChange}>
</Search>
listItems component
import type {Items} from '../../Models/Items.model';
import {dataItems,dispatcher} from './store.svelte';
export let items:Items[] =[];
export let value:any;
$:filterItems = items;
$: {
filterItems = $dataItems.filter((item:any) => {
return item.name || item.description
});
dispatcher.filterInfo(value);
}
</script>
<main>
{#each [...filterItems] as item }
<CardItems
name={item.name}
description={user.description}
id={item.id}
/>
{/each}
</main>
The question is how to communicate both components with the value that you write in the input and make the filter.
Upvotes: 5
Views: 9677
Reputation: 5492
You can accomplish this using a derived store. Here is a small example.
Set up three stores: term
will hold the term being searched for, items
will hold the full list of items, and filtered
will be a derived store that contains the items that include the term. It will automatically be updated whenever term
or items
change.
// stores.js
import { writable, derived } from 'svelte/store';
export const term = writable('');
export const items = writable(['dog', 'cat', 'fish', 'iguana']);
export const filtered = derived(
[term, items],
([$term, $items]) => $items.filter(x => x.includes($term))
);
You can then use these stores across your application. Your Search component can set the term being searched for like so.
<!-- Search.svelte -->
<script>
import {term} from './stores.js';
let val = '';
$: term.set(val);
</script>
<label for="searchInput">Search</label>
<input bind:value={val} type="text" id="searchInput">
When you call term.set(val)
, the derived store will automatically be updated. You can use this store in any component in your application.
<!-- ListItems.svelte -->
<script>
import { filtered } from './stores.js';
</script>
<ul>
{#each $filtered as item}
<li>{item}</li>
{/each}
</ul>
You can see a working example in the Svelte REPL.
Upvotes: 13