I have a table as a component, and now I am trying to build a column wise search within it. The table that will be created will have a dynamic number of columns. Hence I need to create multiple variables for binding with the search input. I was trying to create those variables with eval (unsuccessfully, because I cannot use eval with svelte functionalities like writable or $:).
Note: the main restrictions I have are,
Note: Doing first time front end development, coming from Mainframes backend dev.
I have tried to replicate my scenario in the below repl (not working.. but you will get gist): https://svelte.dev/repl/42335b2b121a402da1c5cd6c826bb5df?version=4.2.19
Expectation: Need the value from any of those inputs to $searchColumn and the corresponding column value. Based on this I will use it to perform next set of tasks. Please see a working version of the scenario but with static defined variables: https://svelte.dev/repl/fa3bd4c83d53421ea0eb3ae5936b401c?version=4.2.19
It seems to me that if you know that the dynamic variables will be a Writable store then there's no reason not to put them inside of an object or array and subscribe to them inside your Search component.
Based on your provided REPLs I came to this solution using the classic Svelte Context with Stores to update the column
and searchColumn
variables from the Search component whenever the input value changes. Unfortunately the typeWorkaround
you included messes up with Svelte's reactivity so I wouldn't recommend using it (same for using eval()
).
This is what the functionality code I think you're looking for looks like in a REPL
<script>
import { setContext } from 'svelte';
import Search from './SearchPretend.svelte'
import { get, writable } from 'svelte/store';
import Subscribe from './Subscribe.svelte';
let externalImpacts = false;
let customComponent = [];
let column = writable(0)
let searchColumn = writable('');
let searchableColumns = {}
setContext("searchColumn", searchColumn)
setContext("column", column)
function createColumns() {
customComponent = [
{accessor: 'Col 0'},
{accessor: 'Col 1', search: true},
{accessor: 'Col 2', search: true},
{accessor: 'Col 3'},
{accessor: 'Col 4'},
{accessor: 'Col 5', search: true},
{accessor: 'Col 6', search: true},
{accessor: 'Col 7', search: true}
]
//loop through object right after creating the columns
customComponent.forEach((obj, i) => {
let searchColName = 'searchColumn_' + i;
if (obj.search === true) {
searchableColumns[searchColName] = writable("")
}
})
}
$: createColumns(), externalImpacts;
function updateColumnWithSearch() {
customComponent.forEach((obj, i) => {
let searchColName = searchableColumns[`searchColumn_${i}`];
if (obj.search === true) {
obj.extra = {
//no problem using get method since this function runs reactively
searchColumn: get(searchColName)
}
}
})
//reassign array to itself to trigger Svelte reactivity
customComponent = customComponent
}
$: if ($searchColumn !== undefined) {
updateColumnWithSearch()
externalImpacts
}
</script>
<h2>
Value: <code>{$searchColumn} </code>
</h2>
<h3>
Column No: <code>{$column}</code>
</h3>
<h3>--------------------------------------------------------------------------------- </h3>
<div class="inputs">
<!-- loop on customComponent to then filter off searchable columns -->
{#each customComponent as column, i}
<!-- use same criteria as in the forEach loop on line 38 -->
{#if column.search === true}
<Search bind:value={searchableColumns[`searchColumn_${i}`]} index={i}/>
<Subscribe value={searchableColumns[`searchColumn_${i}`]}/>
{/if}
{/each}
</div>
<style>
.inputs {
column-count: 5;
font-size: 12px;
}
</style>
Since you know the value must be a writable store, just subscribe in the Search component and update the context from within
<script>
import { getContext } from "svelte";
import { writable } from "svelte/store";
export let value = writable('')
export let index
let searchColumn = getContext('searchColumn')
let column = getContext('column')
function updateContext() {
$column = index
$searchColumn = $value
}
</script>
<div>
<input bind:value={$value} on:input={updateContext}/>
</div>
If you need to display the subscription to the dynamic variable as plain text, you can just use a very simple Subscribe component like this
<script>
export let value
</script>
{$value}
I tried to clarify some stuff with comments but let me know if I wasn't clear, hope this helps you implement the feature!