Home > OS >  How to set a class name dependant on another attribute of the same element in Svelte?
How to set a class name dependant on another attribute of the same element in Svelte?

Time:11-29

I want to set a conditional class based on an attribute of the same element so that I can stay dry. At first I got this:

  <div class="hidden md:flex items-center space-x-3">
    <a href="#Index" class="navBarLink {currentPageName == 'Index' ? 'activeLink' : ''}">Farm</a>
    <a href="#/Leaderboard" class="navBarLink {currentPageName == 'Leaderboard' ? 'activeLink' : ''}">LeaderBoard</a>
    <a href="#/WafBox" class="navBarLink {currentPageName == 'WafBox' ? 'activeLink' : ''}">WafBox</a>
    <a href="#/Buy" class="navBarLink {currentPageName == 'Buy' ? 'activeLink' : ''}">Buy</a>
    <a href="#/Info" class="navBarLink {currentPageName == 'Info' ? 'activeLink' : ''}">Info</a>
</div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Now I would like this:

  <div class="hidden md:flex items-center space-x-3">
    <a href="#Index" class="navBarLink {isActive(this)}">Farm</a>
    <a href="#/Leaderboard" class="navBarLink {isActive(this)}">LeaderBoard</a>
    <a href="#/WafBox" class="navBarLink {isActive(this)}">WafBox</a>
    <a href="#/Buy" class="navBarLink {isActive(this)}">Buy</a>
    <a href="#/Info" class="navBarLink {isActive(this)}">Info</a>
  </div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Then I would simply have to check the attribute of href in my function isActive. But here this does not seem to have the right informations inside. Is there a way to do it ? It would clean my code a lot

Edit: isActive() would look like this:

<script>
  function isActive(element) {
    return 'Active' if (currentPageName == element.attr('href'))
  }
</script>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

One problem with your approach is that both in

<a href="#/Leaderboard" class="navBarLink {isActive(this)}">LeaderBoard</a>

and the proposed answer using the class:directive

 <a href="#Index" class:active-link={isActive('Index')}>Index</a>

is that the function will only run once, at the first render and then never re-execute, not even when currentPageName changes.

The most obvious, straight solution would be to simply ditch the function call and use the class:directive like this:

<a href="#Index" class:active-link={currentPageName == 'Index'}>Index</a>   

this will make sure the classes change as currentPageName changes.

CodePudding user response:

When declaring the function with the arrow syntax and making it reactive by adding $: it looks like alternatively to using the class:directive (which checks if value is truthy/falsy) the classname could be directly set inside the attribute as well

A REPL

<script>
    let currentPageName = 'Index'

    $: isActive = (linkText) => {
        if (linkText === currentPageName) return 'active-link'
        // else if (...) return 'other-class-name' // possible class name switch
        else return ''
    }  
</script>

  <div class="">
    <a href="#Index" class="{isActive('Index')}">Index</a>   
  </div>
  <div class="">
    <a href="#Leaderboard" class="{isActive('Leaderboard')}">Leaderboard</a>   
  </div>

<br>
<button on:click={() => currentPageName = 'Leaderboard'}>change currentPageName</button>

<style>
    .active-link {
        color: purple;
    }
</style>
  • Related