How can I handle the data between depending tables/Components in Svelte?

Viewed 36

I want to display 3 different tables in a specific way on one page(See Tables Overview).
The tables are structured the following way:

Datastructure table A: id1,...
Datastructure table B: id1, id2,...
Datastructure table C: id1, id2, id3,...

The tables should filter results from A to C. In the beginning only table A shows data. After you click on a row in table A, then table B should only show results that have the same id1 as table A (A.id1 = B.id1). When you select a row in table B, then C should also only show matching results( .filter(e => e.id1 == bID1 && e.id2 == bID2 ).

The records are jsonObjects in an Array(per Table).

What would be a good way to implement this behavior?

I don't necessarily need the code, just some thoughts how to tackle this problem.

What I tried/used:

  • data stored in stores
  • I reused my tableComponent for all tables -> Should i create a component for each table?

Thank you!

1 Answers

Such a Table component basically needs to know three things

  • the data to display
  • the filters that should be applied before displaying the data
  • the filter that is set/defined by clicking on a row

Here's a REPL with a component that looks like this

<script>
    export let data = []
    export let filter = ['', ''] // [filterKey, filterValue]
    export let filterDataBy = []

    $: displayData = data.filter(d => {
        const filterChecks = filterDataBy.map(([filterKey, filterValue]) => {
            return d[filterKey] === filterValue
        })
        return filterChecks.every(check => check === true)
    })
</script>

<div>
    <span style:color={filter[0] ? '' : 'transparent'}>
        Set {filter[0]} : <b>{filter[1]}</b>
    </span>
    <table>
        <tr>
            {#each Object.keys(data[0]) as key}
            <th>
                {key}
            </th>
            {/each}
        </tr>
        {#each displayData as d}
        <tr class:selected={d[filter[0]] === filter[1]}
                on:click={() => filter[1] = d[filter[0]]}
            >
            {#each Object.values(d) as value}
            <td class:bold={value === filter[1]}>
                {value}
            </td>
            {/each}
        </tr>
        {/each}
    </table>
</div>

<style>
    div {
        display: inline-block;
    }
    table {
        border-collapse: collapse;
        border: 1px solid black;
        margin-top: .3rem;
        padding: .3rem 0;
        cursor: default;
        user-select: none;
    }
    td {
        padding: .2rem;
    }
    .selected {
        background: lightgrey;
    }
    .bold {
        font-weight: bold;
    }
</style>

and is used like this

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

    const data = [
        ...
    ]

    let f1 = ['name', '']
    let f2 = ['age', '']

</script>

<Table {data} bind:filter={f1} />
<Table {data} bind:filter={f2} filterDataBy={[f1]}/>
<Table {data} filterDataBy={[f1,f2]}/>
Related