Reactive Data


Useful Links

Actions


Table Demo


NameAgeEmailPhone
Tracy Ondricka59Cody.Hahn46@hotmail.com(270) 685-2088
Dr. Delores Greenholt86Jermain22@gmail.com(670) 634-8446
Lena Hagenes90Rosalind.Bins55@hotmail.com(388) 742-7727
Dr. Dallas Bogisich67Will_Orn@yahoo.com(987) 878-2091
Frances Hackett-Ullrich30Morton.Reichert4@hotmail.com(398) 339-5972
Miss Katherine Strosin47Josh_Dare@yahoo.com(522) 311-0039
Kim Ziemann II41Jacquelyn.Zemlak@yahoo.com(442) 360-5473
Al Krajcik63Georgiana.Howe21@yahoo.com(717) 941-5844
Lucille Sporer67Bernard.Purdy12@hotmail.com(706) 648-9699
Elizabeth White88Benny_OKeefe69@yahoo.com(884) 678-5353

Explanation


In this guide, we'll extend your knowledge of creating a table in Svelte by focusing on handling reactive data.

Before proceeding, you should already know how to create and render a basic table.

Adding Data to a $state Rune

The first step is to make the data reactive by storing it in a $state. In Svelte 5, $state is a signal that allows you to track and update state changes in a reactive manner. This ensures that when the data changes, the table will automatically update to reflect those changes.

<script lang="ts">
  type Props = {
    data: PageData;
  };

  let { data }: Props = $props();
  let { userProfiles } = data;

  // Create a reactive state for the user profiles data using a $state rune.
  let dataState = $state(userProfiles);
</script>

Creating the Table

To make the table reactive, we need to pass the data property as a getter function to createSvelteTable. This approach ensures that the table dynamically responds to changes in dataState.

<script lang="ts">
  import { type UserProfile } from '$lib/services/user-profile'; 
  import { createColumnHelper, createSvelteTable, getCoreRowModel } from '$lib/table'; 

  type Props = {
    data: PageData;
  };

  let { data }: Props = $props();
  let { userProfiles } = data;

  let dataState = $state(userProfiles);

  const colHelp = createColumnHelper<UserProfile>(); 

  const columnDefs = [ 
    colHelp.accessor('name', { header: 'Name' }), 
    colHelp.accessor('age', { header: 'Age' }), 
    colHelp.accessor('email', { header: 'Email' }), 
    colHelp.accessor('phone', { header: 'Phone' }) 
  ]; 

  const table = createSvelteTable({ 
    // The data field is defined as a getter to ensure it is reactive.
    get data() { 
      return dataState; 
    }, 
    columns: columnDefs, 
    getCoreRowModel: getCoreRowModel() 
  }); 
</script>
  • Reactive Data: By implementing the data property as a getter, any change to dataState will automatically trigger the table to re-render with the updated data.
  • Benefit: This setup makes the table's data handling straightforward and automatically keeps it in sync with state changes.

Mutating Data

We will create two functions to modify the table data: one to add a record at the beginning and another to remove the last record. It's crucial to reassign the dataState variable when updating the data to ensure reactivity.

<script lang="ts">
  import { type UserProfile } from '$lib/services/user-profile';
  import { createColumnHelper, createSvelteTable, getCoreRowModel } from '$lib/table';

  type Props = {
    data: PageData;
  };

  let { data }: Props = $props();
  let { userProfiles } = data;

  let dataState = $state(userProfiles);

  const colHelp = createColumnHelper<UserProfile>();

  const columnDefs = [
    colHelp.accessor('name', { header: 'Name' }),
    colHelp.accessor('age', { header: 'Age' }),
    colHelp.accessor('email', { header: 'Email' }),
    colHelp.accessor('phone', { header: 'Phone' })
  ];

  const table = createSvelteTable({
    get data() {
      return dataState;
    },
    columns: columnDefs,
    getCoreRowModel: getCoreRowModel()
  });

  function prependRecord() { 
    dataState = [UserProfileService.getOne(), ...dataState]; 
  } 

  function popRecord() { 
    dataState = dataState.slice(0, dataState.length - 1); 
  } 
</script>

<div class="actions-wrapper">
  <h2>Actions</h2>
  <hr />
  <button onclick={() => prependRecord()}> Prepend a Record </button>
  <button onclick={() => popRecord()}> Pop a Record </button>
</div>

🗒️ Note: The dataState variable must be reassigned after mutation (dataState = ...) to ensure that the change is detected and triggers an update in the UI.

Rendering the Table in the Markup

Finally, we render the table using Svelte's templating syntax. Since the table data is reactive, it will automatically update when you modify dataState using the functions created above.

<table>
  <thead>
    <tr>
      {#each table.getHeaderGroups() as headerGroup}
        {#each headerGroup.headers as header}
          <th>
            <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
          </th>
        {/each}
      {/each}
    </tr>
  </thead>
  <tbody>
    {#each table.getRowModel().rows as row}
      <tr>
        {#each row.getVisibleCells() as cell}
          <td>
            <FlexRender content={cell.column.columnDef.cell} context={cell.getContext()} />
          </td>
        {/each}
      </tr>
    {/each}
  </tbody>
</table>