I have a select in my svelte app. I cannot get it to display it's initial value (default_car) or, after I have clicked on a car, the selected_car
App.svelte
<Car {cars} on:message={carChanged} /> <div> <button on:click={getDataStore}>Get data</button> </div> <script> import Car from './Cars.svelte' import { getBlankCars, getCarData } from './store.js' let cars = getBlankCars(); let car; function carChanged(event) { car = event.detail.value; console.log('selected car:', car); } function getDataStore() { cars = getCarData(); } </script> Cars.svelte
<select bind:value={selected_car} on:click={selectCar}> {#each car_list as car} <option value={car}> {car} </option> {/each} </select> <script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); let started = false; export let cars; $cars = $cars; let car_list; $: car_list = carList($cars); let default_car = 'BMW'; let selected_car; $: selected_car = getInitialCar($cars) $: selected_car = default_car function getInitialCar() { if (!started) { selected_car = default_car; if (selected_car) { started = true; selectCar(); } } selected_car = default_car } function carList(cars) { let car_list = []; for (const [key, value] of Object.entries(cars)) { car_list.push(key); } return car_list; } function selectCar() { dispatch('message', { value: selected_car }); } </script> store.js
import { writable } from 'svelte/store' let blank_cars = {} let raw_cars = {'Audi': 'red', 'Aston Martin': 'silver', 'BMW':'blue', 'Bugatti': 'black', 'Hillman': 'green'} export function getBlankCars() { return writable(blank_cars) } export function getCarData() { return writable(raw_cars) } What can I do to get the select to display the value?
1 Answer
I think you can reduce the code in Cars.svelte to this REPL - does this function the way you want it to?
Three things to mention
- if you have an object as store value and want to display the content in an
{#each}loop you don't have to generate a new array, but can directly iterate inside each with{#each Object.keys($cars) as car}or{#each Object.entries($cars) as [key, value]} - change
on:clicktoon:change={selectCar} - the
<script>block below the html is unusual ~ the more common order (like in the Svelte tutorial) is script - html - style/css
<script> import { createEventDispatcher } from 'svelte'; const dispatch = createEventDispatcher(); export let cars; let selected_car = 'BMW'; // set default value here function selectCar() { dispatch('message', { value: selected_car }); } </script> <select bind:value={selected_car} on:change={selectCar}> <!-- reduce code by directly iterating $cars via (obj) --> {#each Object.keys($cars) as car} <option value={car}> {car} </option> {/each} </select> 5