Closed marioaldairsr closed 5 months ago
In ThFilter.svelte
, since the key is the variable, you should pass it directly as the filter param rather than using a callback:
handler.filter(value, key)
instead of:
handler.filter(value, (row) => row[key])
Then, as you mentioned, the parseField()
function will determine that "key" is of type "string", and will create the callback.
The identifier will contain the actual value of "key" instead of "row[key]"
@vincjo, thanks for your reply.
We have a use case where we could have a nested object like this:
const data = [
{
name: 'Mario',
status: 'DRAFT',
ammount: 41,
job: {
id: 5,
name: 'Developer'
}
},
{
name: 'George',
status: 'OPEN',
ammount: 54,
job: {
id: 6,
name: 'Sales'
}
},
{
name: 'Mario',
status: 'OPEN',
ammount: 31,
job: {
id: 7,
name: 'Engineer'
}
}
];
And this is a model that can have more or fewer key properties; it's dynamic, that's why can't have a custom filter for each of them. So we are using the callback like this:
(row) => getPropertyValue(row, key)
where key could be 'jobs.id', 'name', 'jobs.name', etc...
@vincjo, I was able to solve the problem with the following code, creating a dynamic function to ensure that when converted to a string it's always unique:
function createNamedFunction(key) {
return new Function('row', `
function getValueByPath(obj, path) {
return path.split('.').reduce((currentObject, key) => {
return currentObject ? currentObject[key] : undefined;
}, obj);
}
return getValueByPath(row, '${key}');`);
}
handler.filter(value, createNamedFunction(key), check.contains);
Oh, ok. Nice
I also added a workaround in version 1.14.3
(this library needs a better way to name filters).
You can choose what best suits your needs.
In ThFilter.svelte
<script lang="ts">
import type { DataHandler } from '$lib';
export let handler: DataHandler;
export let key: any = '';
let value = '';
const filter = handler.createFilter((row) => row[key])
</script>
<th>
<input
type="text"
placeholder="Filter"
bind:value
on:input={() => filter.set(value)}
/>
</th>
Instead of handler.filter()
shortcut, you declare a new filter instance, by using handler.createFilter()
.
This instance creates a random string as a unique identifier.
Thanks for raising this point
Cool. Thank you so much for your help. I'll close this.
@vincjo, sorry for open it again. Just want to ask if is it the same case with the sort function?
Indeed, didn't think about it. I added a workaround for column sorting, where you can pass an identifier to the sort method.
Released in 1.14.4
.
Using handler
instance:
handler.sort(orderBy, identifier)
Using <Th>
component:
<Th orderBy={(row) => row[key]} identifier="th0"/>
Using your code example:
<table>
<thead>
<tr>
{#each keys as key, i}
<Th {handler} orderBy={key} identifier={'th' + i}>{key}</Th>
{/each}
</tr>
[...]
Okay, it looks nice. Thank you. Is there a way to have multiple sorts?
For example:
Sort by id asc Then by amount desc Then by date asc
To solve this, I just have to create a custom sort function and then reset the rows with handler.setRows(sortedRows)
There is a way:
handler.sortAsc('id')
handler.sortDesc('amount')
handler.sortAsc('date')
(You can add an identifier as a second parameter)
When you update rows using setRows()
, last 3 sorts are played automatically.
I have an application that displays a table with the keys name of an object, and it needs to be dynamically filtered based on those keys but it doesn't work as expected.
To replicate:
Main.svelte
ThFilter.svelte
This is not working as expected; every time I filter, it resets everything.
I was looking into the package's source code and I found that it parses the function to a string and sets it as an identifier. So, if I put the function as
(row) => row[key]
, that becomes the identifier. When it tries to filter, it replaces the last function.utils.js
There is another solution for this?