sveltecarbon-componentscarbon-components-svelte

How to access the cells display text ( instead of value ) inside a Carbon DataTable?


I have a Sveltekit project using Carbon components. Given an example table based on objects { title: string; priceInEuros: number | null; link: string; } that should display the following

Reproduction link

<link rel="stylesheet" href="https://unpkg.com/carbon-components-svelte/css/white.css"/>

<script>
    import { DataTable } from 'carbon-components-svelte';
  
    $: tableItems = [
        { title: "Item 1", priceInEuros: 5.43, link: "link to item 1" },
        { title: "Item 2", priceInEuros: null, link: "link to item 2" },
        { title: "Item 3", priceInEuros: 1.82, link: "link to item 3" }
    ]
        .map((item, itemIndex) => {
            return {
                id: itemIndex,
                ...item
            };
        });

    $: tableHeaders = [
        {
            key: 'priceInEuros',
            value: 'priceInEuros',
            display: (priceInEuros) => {
                if (!priceInEuros) {
                    return '';
                }

                return priceInEuros.toLocaleString('de-DE') + '€';
            },
            sort: (leftPriceInEuros, rightPriceInEuros) => {
                return (leftPriceInEuros ?? 0) - (rightPriceInEuros ?? 0);
            }
        },
        {
            key: 'title',
            value: 'title',
            sort: false
        }
    ];
</script>

<DataTable sortable size="compact" headers={tableHeaders} rows={tableItems}>
    <svelte:fragment slot="cell" let:row let:cell>
        {#if cell.key === 'title'}
            <a href={row['link']} target="_blank">{cell.value}</a>
        {:else}
            {cell.value}
        {/if}
    </svelte:fragment>
</DataTable>

The output is

enter image description here

The price column is wrong. That's because the table is using the "raw" cell value in the else statement inside the slot.

I don't need the else statement but when removing it the price column is empty. So I think I have to implement the else statement but I'm looking for something like cell.displayValue.

Do you have any ideas?


First approach

I could replace the content inside the else statement with

{:else if tableHeaders.find((header) => header.key === cell.key)?.display === undefined}
    {cell.value}
{:else}
    {tableHeaders.find((header) => header.key === cell.key)?.display(cell.value)}
{/if}

Solution

  • cell.display(cell.value) should do the work

    <DataTable sortable size="compact" headers={tableHeaders} rows={tableItems}>
        <svelte:fragment slot="cell" let:row let:cell>
            {#if cell.key === 'title'}
                <a href={row['link']} target="_blank">{cell.value}</a>
            {:else}
                {cell.display ? cell.display(cell.value) : cell.value}
            {/if}
        </svelte:fragment>
    </DataTable>