Home > Enterprise >  How do I filter lists, retrieved via async await, in Svelte?
How do I filter lists, retrieved via async await, in Svelte?

Time:04-02

I'm using Svelte for the first time, and I'm trying to figure out how to apply filtering to a list retrieved from an API. My EventsIndex component is very simple, and comprises the following logic:

import FetchPosts from '../services/postsByType'
import EventCard from '../components/EventCard.svelte'

export let post_type

let events = new FetchPosts( post_type ).get()
let currentCategory = 0

function updateCategory( catId ) {
    currentCategory = catId
}

Everything works just as expected.

I'm also using the await template syntax to display the relevant data:

{#await events}
    <h1>loading...</h1>
{:then events}
    <section >
        {#each events as event}
            <EventCard event={event} on:filter={updateCategory}/>
        {/each}
    </section>
{:catch error}
    <p>Something went wrong...</p>
{/await}

The missing piece is the reactive filtered list. I thought I could do the following, but it generates the error events.map is not a function, which makes sense, as the events variable would be an unresolved promise when filteredEvents is invoked.

$: filteredEvents = () => {
    if (currentCategory === 0) return events

    return events.filter( event => {
        return event.categories !== null
            ? event.categories.some( cat => cat.id == currentCategory )
            : false
    })
}

So how would I add a reactive filteredEvents function, that I can also include in my template?

CodePudding user response:

Filtering on the events inside the {#each} loop should work. If the filter function was very short like this I'd apply it inline

{#each events.filter(e => e.id === currentId) as event}

Just as an example. Since in your case the filter function is more complex, moving it to a function might be the better option

filterEvents(events, currentCategory) {
    if (currentCategory === 0) return events

    return events.filter( event => {
        return event.categories !== null
            ? event.categories.some( cat => cat.id == currentCategory )
            : false
    })
}
</script>

...

{#each filterEvents(events, currentCategory) as event}

(I think you can replace this

 return event.categories !== null
            ? event.categories.some( cat => cat.id == currentCategory )
            : false

by this

event?.categories.some( cat => cat.id === currentCategory )
  • Related