how to work with data models in svelte 5 (example: Product, Product[])

in svelte 4, I used the following approach:

<script lang="ts">
    class Product {
        id: number = 0;
        name: string = "";
        description: string = "";
    }
    let products: Product[]=[];
    let productForAdd = new Product();
</script>
}

<div>
    <input bind:value={product.name} />
    <input bind:value={product.description} />
    <input bind:value={product.image} />

    <button on:click={() => {
        products = [...products, productForAdd];
        productForAdd = new Product();}>
            Add
    </button>
</div>

{#each products as product}
    <div>
        <div>{product.id}</div>
        <div>{product.name}</div>
        <div>{product.description}</div>
    </div>
{/each}

How can I do the same in svelte 5? If I use the Product class without runes, then errors about the lack of reactivity appear. If I add the state rune to a class, I cannot get data from an object created based on this class, $state.snapshot(products) turns out to be empty. And if I add a nested array with other objects to the Product class, for example, of this type:

   class Category {
        name: string = "";
        description: string = "";
    }

   class Product {
        id: number = 0;
        name: string = "";
        description: string = "";
        categoryes: Category[]=[];
    }

It turns out to be a complete trash

Upvotes: 0

Views: 84

Answers (1)

Sean Vieira
Sean Vieira

Reputation: 160043

The goal of Svelte is always to make the unnecessary bits disappear. So all you need to do is annotate your changable state with $state and everything else will just work.

<script lang="ts">
class Product {
    id: number = 0;
    name: string = "";
    description: string = "";
    categories: Category[] = [];
}

class Category {
    name: string = "";
    description: string = "";
}
let categories = $state([]);
let newCategory = $state(new Category());

let products: Product[] = $state([]);
let newProduct = $state(new Product());
</script>

<div>
    <fieldset>
        <legend>Category</legend>
        <input bind:value={newCategory.name}>
        <input bind:value={newCategory.description}>
        <button onclick={() => {
            categories.push(newCategory);
            newCategory = new Category(); }}>
            Add
        </button>
    </fieldset>

    <fieldset>
        <legend>Product</legend>
    <input bind:value={newProduct.name} />
    <input bind:value={newProduct.description} />
    <select multiple bind:value={newProduct.categories}>
            {#each categories as category }
            <option value={category}>{category.name}</option>
            {/each}
        </select>
    <button onclick={() => {
        products = [...products, newProduct];
        newProduct = new Product();}}>
            Add
    </button>
    </fieldset>
</div>

{#each products as product}
<dl>
    <dt>{product.name}</dt>
    <dd>{product.description}<br>
    <ul>
        {#each product.categories as category}
            <li>#{category.name}</li>
        {/each}
    </ul>
    </dd>
</dl>
{/each}

Upvotes: 0

Related Questions