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>