Vue class binding attribute and multiple tailwind classes - javascript

I'm trying to bind an attribute and multiple tailwind classes to an html element. This is for a tab menu, so the idea is that for the "active" tab I take the title dynamically and inject also some tailwind classes to change the look and feel of the "active" tabs.
<li
:class="{
selected: title === selectedTitle,
selected ? ['border-b-2', 'border-blue-700' ]
}"
#click.stop.prevent="selectedTitle = title"
v-for="title in tabTitles"
:key="title"
role="presentation"
>
At the moment the previous code is not working for me.

From my point of view following line can't work:
selected ? ['border-b-2', 'border-blue-700' ]
This is a short if else without an else case - I think you ment writing something like this:
<li :class="{
'selected border-b-2 border-blue-700': title === selectedTitle,
}">

Try like following:
new Vue({
el: "#demo",
data() {
return {
tabTitles: ['aaa', 'bbb', 'ccc'],
selectedTitle: ''
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" integrity="sha512-wnea99uKIC3TJF7v4eKk4Y+lMz2Mklv18+r4na2Gn1abDRPPOeef95xTzdwGD9e6zXJBteMIhZ1+68QC5byJZw==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<div id="demo">
<li :class=" selectedTitle === title ? 'border-b-2 border-blue-700' : '' "
#click.stop.prevent="selectedTitle = title"
v-for="title in tabTitles"
:key="title"
role="presentation"
>{{title}}</li>
</div>

Related

how to add multiple bind multiple classes to element with multiple booleans using v-bind:class

I am trying to assign classes into an element depending on whether or not a boolean is true. I was able to do this using v-bind:class for some classes. However now I want to do this again for another boolean at the same time. This is for a to-do list app.
my current code:
<div
v-bind:class="[task.checked ? '!bg-gray-800 text-gray-600 line-through' : 'none']"
v-bind:class="[task.checked ? '!bg-gray-800 text-gray-600 line-through' : 'none']"
class="tasks_container grid grid-cols-10"
v-for="task in tasks"
>
<!-- task for loop -->
</div>
data() {
return {
note_text: ' ',
tasks: [
{
text: 'hello',
checked: false,
selected: true
},
{
text: 'world',
checked: false,
selected: false
}
]
};
},
I tried doing :
<div
v-bind:class="[task.checked ? '!bg-gray-800 text-gray-600 line-through' : 'none']"
v-bind:class="[task.selected ? '!bg-gray-100' : 'none']"
class="tasks_container grid grid-cols-10"
v-for="task in tasks"
>
<!-- task for loop -->
</div>
this didn't work because you cant have multiple v-bind:class
I also tried :
<div
v-bind:class="[task.checked?'!bg-gray-800 text-gray-600 line-through':'none'], ['task.selected? !bg-gray-100':'none']"
v-for="task in tasks"
>
<!-- task for loop -->
</div>
that didn't work but I forget what is said for why. I'm sorry if my code has weird please let me know how I can fix that I'm new to stackoverflow and any help is appreciated.
Vue documentation has an example of binding classes using multiple data properties. Yours can be written like this:
<div
:class="{ '!bg-gray-800 text-gray-600 line-through': task.checked, '!bg-gray-100': task.selected }"
v-for="task in tasks"
>
To achieve this requirement, You can pass an object to v-bind:class directive to dynamically toggle the classes.
Live Demo :
new Vue({
el: '#app',
data() {
return {
tasks: [
{
text: 'hello',
checked: true,
selected: true
},
{
text: 'world',
checked: false,
selected: true
}
]
};
}
})
.text-gray-600 {
color: gray;
}
.line-through {
text-decoration: line-through;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div
v-for="(task, index) in tasks"
:key="index"
:class="{ '!bg-gray-800 text-gray-600 line-through': task.checked, '!bg-gray-100': task.selected }"
>
{{ task.text }}
</div>
</div>

Apply an Class by using VueJS condition

I'm trying to apply a class to a <p> tag using a VueJS condition but it doesn't work at all, despite it working on JSfiddle. It's been 3 days now that I'm stuck, please help me.
VueJS (in main.js)
new Vue({
el: "#test",
data: {
selected: "2"
}
});
HTML (App.vue)
<div id="app">
<div id="test">
{{ selected }}
<p :class="{ selection: 1 === selected }">
heyyy 1
</p>
<p :class="{ selection: 2 == selected }">
heyyy 2
</p>
<button #click="selected = 2">Switch</button>
</div>
</div>
I'll assume you're using Vue-CLI since you have a .vue file, but your main.js is using syntax from Vue CDN. Maybe you copied the code from the fiddle instead.
I'll assume too that you have a CSS class named .selection for this to work.
Either way, App.vue has its own component instance which is not the main.js mounting instance (it's one level deeper). Your code creates selected in the mounting root instead of App.vue.
To fix, create it in App.vue <script> section instead:
<template>
<div id="app">
<div id="test">
{{ selected }}
<p :class="{ selection: 1 === selected }">
heyyy 1
</p>
<p :class="{ selection: 2 == selected }">
heyyy 2
</p>
<button #click="selected = 2">Switch</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
selected: "2"
}
}
}
</script>
<style>
.selection {
/* CSS */
}
</style>
to apply class binding in VueJs you can use it as :
:class="{ 'selection(your class name here)': selected === 1}"

Active class not reactive on the first load using vue.js

So I am building a tab component and using :class to bind the active class like this.
<nav class="tabs__header" >
<ul>
<li>
<a
ref="tabItems"
v-for="(tabItem, idx) in tabs"
:key="tabItem.idx"
:class="{ 'b-active': idx === selectedIndex }"
#click="changeTab(idx)">
<span v-if="icon"> {{ tabIcon }} </span>
{{ tabItem.name }}
</a>
</li>
</ul>
</nav>
The selectedIndex is set with tabIndex value when mounted() for the first time and updated based on the 'idx' selected afterward. I have no problem with the b-active class if we click the tab manually, but it not bind the tabIndex value assigned in mounted().
This is the script I use to directly add value '0' for testing and still not get anything.
props: {
tabIndex: {
type: String,
default: '0'
},
mounted() { this.selectedIndex = this.tabIndex }
can anyone help me? because it seems very simple and I couldn't figure it out for 2 days
The problem solved and it turns out to be the data type problem, apparently tabIndex is a String and selectedIndex is a Number.
I changed:
:class="{ 'b-active': idx === selectedIndex }"
to:
:class="{ 'b-active': idx == selectedIndex }"
and it worked!
At initial render idx seems to be undefined.
Replace this:
:key="tabItem.idx"
With this:
:key="idx"
This now should work fine.
Alternatively, you may use v-for like:
v-for="tabItem in tabs"
Now, using tabItem.idx works just fine as you do in others like tabItem.name.
So, here's your code updated:
<nav class="tabs__header" >
<ul>
<li>
<a
ref="tabItems"
v-for="tabItem in tabs"
:key="tabItem.idx"
:class="{ 'b-active': tabItem.idx == selectedIndex }"
#click="changeTab(idx)">
<span v-if="icon"> {{ tabItem.icon }} </span>
{{ tabItem.name }}
</a>
</li>
</ul>
</nav>

toggle active class on list menu items - vue js

I want that, clicking on a menu item, the active class is triggered only for that specific item and removed for the others, until now I wrote this:
<template>
<nav class="navbar">
<div class="navbar__brand">
<router-link to="/">Stock Trader</router-link>
</div>
<div class="navbar__menu">
<ul class="navbar__menu--list">
<li #click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
<router-link to="/portfolio">Portfolio</router-link>
</li>
<li #click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
<router-link to="/stocks">Stocks</router-link>
</li>
</ul>
</div>
<div class="navbar__menu--second">
<ul class="navbar__menu--list">
<li #click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
End Day
</li>
<li #click="isActive=!isActive" class="navbar__menu--item" :class="{active:isActive}">
Save / Load
</li>
</ul>
</div>
</nav>
</template>
<script>
export default {
data(){
return{
isActive: false
}
}
}
</script>
now of course, when I click on one item the active class is inserted/removed for all the items, what is the best solution for making that only a specific item, on clicking on it, receives the active class?
You'll want some sort of identifier for each clickable item and set that to your data property. For example
data() {
return { active: null }
}
and in your list items (for example)
<li #click="active = 'portfolio'"
class="navbar__menu--item"
:class="{active:active === 'portfolio'}">
In this example, the identifier is "portfolio" but this could be anything, as long as you use a unique value per item.
You could keep an object of links you have and handle a click on each of items. E.g.
data() {
return {
links: [
{
title : 'Portfolio',
to : '/portfolio',
isActive : false,
location : 'first',
},
{
title : 'Stocks',
to : '/stocks',
isActive : false,
location : 'first',
},
{
title : 'End Day',
to : '#',
isActive : false,
location : 'second',
},
{
title : 'Save / Load',
to : '#',
isActive : false,
location : 'second',
},
]
};
},
methods: {
handleNavClick(item) {
this.links.forEach(el, () => {
el.isActive = false;
});
item.isActive = true;
}
},
I do this in vue3.
the template is:
<li
v-for="(title, index) in titles"
class="title"
:key="index"
:class="{ active: active === index }"
#click="updateActive(index)"
>
{{ title }}
</li>
and the script is
<script lang="ts" setup>
import { ref } from "vue"
const titles = ["title1","title2","title3"]
const active = ref(-1)
function updateActive(val: number) {
active.value = val
}
</script>
If you have several ul => use title instead of index. For example :
<ul>
<div>
Applicants
</div>
<li
v-for="(title, index) in applicantMenuTitles"
:key="index"
:class="{ active: active === title }"
#click="updateActive(title)"
>
{{ title }}
<div
v-if=" active === title "
class="cursor"
/>
</li>
</ul>
<ul>
<div>
Offices
</div>
<li
v-for="(title, index) in officeMenuTitles"
:key="index"
:class="{ active: active === title }"
#click="updateActive(title)"
>
{{ title }}
<div
v-if=" active === title "
class="cursor"
/>
</li>
</ul>
And on script :
...
const active = ref('')
function updateActive(title: string) {
active.value = title
}

ng-class does not change class unless I refresh the page

I'm using ng-class in my view to change the class of and element and it works fine on page load. Here is my code:
<ul>
<li ng-class="'{{account.currency}}' == '{{currency}}' ? 'active': 'inactive'" ng-repeat="account in accounts" bind="accounts">
<a href="#/deposits/{{account.currency}}" ng-click="changeClass('{{account.currency}}', '{{currency}}')">
{{currency}}
</a>
</li>
<ul>
As you can see, it takes the second currency from the URL and compares it with another to decide which class it should assign to my li element.
The trouble now is that when someone clicks on the link and the URL changes, the class assigned does not change. Any idea how I can get the class assigned by ng-class to change when the
You don't need to call a function for this, this can be easily achieved inline
try like this:
<li ng-class="{'active' : account.currency == currency, 'inactive':
account.currency != currency}">
OR
<li ng-class="{true: 'active', false: 'inactive'}[account.currency == currency]">
If you're using angular v.1.1.4+
<li ng-class="account.currency == currency ? 'active': 'inactive'}">
Try this,
var app = angular.module('app', []);
app.controller('myctrl', function() {
var vm = this;
vm.accounts = [{
currency: 'Doller'
}, {
currency: 'Pound'
}, {
currency: 'Euro'
}];
vm.changeClass = function(account) {
vm.active = account.currency;
}
});
.active {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body>
<div ng-app="app" ng-controller="myctrl as ct">
<ul>
<li ng-class="{'active': ct.active === account.currency}" ng-repeat="account in ct.accounts">
<a href="#" ng-click="ct.changeClass(account)">
{{account.currency}}
</a>
</li>
</ul>
</div>
</body>
Make the ng-class= {'active': account.currency === currency}
in the css file you should have the .active{} class. And let the inactive class be the default behaviour.
P.S The answers of Dhaval should work also

Categories

Resources