I have a svelte application and I wish to highlight a row when the user clicks on it; similar to this simple code:
<div id="A" >A</div>
<div id="B" >B</div>
<style>
.car-even {
color: #008800;
cursor: pointer;
}
.car-odd {
color: red;
cursor: pointer;
}
.car-selected {
color: blue;
background-color: #ffffaa;
cursor: pointer;
}
</style>
<script>
row = document.getElementById('A')
row.className = 'car-selected '
</script>
But in svelte the className does not seem to be updated correctly. What is wrong?
App.svelte
<script>
import Car from './cars.svelte'
let car = ''
$: console.log('Car', car)
</script>
<Car bind:selected_car={car}/>
Cars.svelte
<script>
let cars = ['Audi', 'BMW', 'Hillman', 'Hyundai', 'Jaguar']
export let selected_car = ''
let car_class = ['car-even', 'car-odd']
function carClicked(car) {
selected_car = car
let car_row = document.getElementById(car)
car_row.className = 'car-selected'
}
</script>
{#each cars as car, index (car)}
<div id={car} on:click={() => carClicked(car)}>{car}</div>
{/each}
<style>
.car-even {
color: #008800;
cursor: pointer;
}
.car-odd {
color: #000088;
cursor: pointer;
}
.car-selected {
background-color: #ffffaa;
cursor: pointer;
}
</style>
CodePudding user response:
Your example doesn't seem to work, because the .car-selected
css class isn't compiled, because it's not used anywhere (the compiler knows of). If you have a look at the html, the class gets added on click (but this also overwrites/removes the other class)
If you add :global()
modifier :global(.car-selected)
, you see the class is applied
To do it the Svelte way, use the class:directive instead and add this to the div inside the each loop
class:car-selected={car === selected_car}
You could then get rid of carClicked()
if you wanted REPL
{#each cars as car, index (car)}
<div id={car}
class:car-selected={car === selected_car}
on:click={() => selected_car = car}
>
{car}
</div>
{/each}
(( why not reduce repetition and make use of Svelte's scoped styling and add
div {
cursor: pointer;
user-select: none;
}
))