Home > Blockchain >  How to set an element's class in svelte
How to set an element's class in svelte

Time:03-16

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;
    }

))

  • Related