vuejs mouseover add class to this element - javascript

How can I add class on mouse over on list item & remove class on mouse leave
<li class="test" #mouseenter="thumbStyle" #mouseleave="thumbStyle2">1</li>
<li class="test" #mouseenter="thumbStyle" #mouseleave="thumbStyle2">2</li>
<li class="test" #mouseenter="thumbStyle" #mouseleave="thumbStyle2">3</li>
In data & methods
data(){
isActive:false
}
thumbStyle:function(){
this.isActive = true;
},
thumbStyle2:function(){
this.isActive = false;
},
I have tried this but it is only adding class to first element (li) when I over on any list(li). So what is the technique to add only this(hovered) li. Like in jquery there are $(this)

The ideal way to handle this is that each of the elements you want to control the state of, are a model, then you can easily manipulate the state of each item.
Here is an example:
new Vue({
el: '#app',
data: function() {
return {
items: [{
label: 'Planes',
active: false
}, {
label: 'Trains',
active: false
}, {
label: 'Automobiles',
active: false
}]
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.15/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in items"
#mouseenter="item.active = true"
#mouseleave="item.active = false"
>{{ item.label }} is {{ item.active }}</li>
</ul>
</div>

I have solved as belows
thumbStyle:function(e){
var clickedElement = e.target;
$(clickedElement).addClass('active');
},
thumbStyle2:function(e){
var clickedElement = e.target;
$(clickedElement).removeClass('active');
},

Related

How to bind value to each list item in Vue to toggle the images

I'm trying to toggle between the 2 images by triggering a function on click event, as shown below, how do I apply the same idea to different list items to toggle the images individually for each item? right now, all the list items same image because of one global value i.e val
var app = new Vue({
el: '#app',
data: function() {
return {
val:true,
selectedImg:"",
checked: "#/assets/images/check.png",
unchecked: "#/assets/images/uncheck.png",
items: [
{ message: 'laundry' },
{ message: 'cooking' },
{ message: 'cleaning'}
]
}
},
methods: {
myfunc () {
this.val = (this.val === true ? false : true)
if(this.val === true) {
this.selectedImg = this.checked
} else {
this.selectedImg = this.unchecked
}
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in items" :key="item.message">
<button #click="myfunc"><img :src="selectedImg"/></button>
{{ item.message }}
</li>
</ul>
</div>
You should move selectedImg and val into items objects and pass item to myfunc function.
You can also look at the answer in codepen.
var app = new Vue({
el: '#app',
data: function() {
return {
checked: "#/assets/images/check.png",
unchecked: "#/assets/images/uncheck.png",
items: [
{ message: 'laundry', selectedImg:"" , val:true},
{ message: 'cooking', selectedImg:"", val:true},
{ message: 'cleaning', selectedImg:"", val:true}
]
}
},
methods: {
myfunc (item) {
item.val = (item.val === true ? false : true)
if(item.val === true) {
item.selectedImg = this.checked
} else {
item.selectedImg = this.unchecked
}
},
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in items" :key="item.message">
<button #click="myfunc(item)"><img :src="item.selectedImg"/></button>
{{ item.message }}
</li>
</ul>
</div>

Vue js show hide element on click

I am new in vue js. I want to show hide elements on click.
So that What I can do -
make a property in data object like
isHidden: false
and add a mehtod like
showHide(){
return this.isHidden = !this.isHidden;
}
And bind the showHide method on click event like
<li #click="showHide">Some text</a>
But the problem is- if there are several list items binding the same click event,
all lists will be shown on click, or all will hide. But I want the
target element will only show or hide by click.
How can I do this, please?
You can use some data to determine what element you want show/hide. For example: id, index of each element
<button v-for="(i, ind) in listElement" #click="toggleElement(ind)" :key="ind">
Toggle {{ i }}
</button>
<p v-for="(i, ind) in listElementShow" :key="ind">
Element: {{ i }}
</p>
Logic:
data() {
return {
listElement: [ { name: 1, isShow: true}, { name: 2, isShow: true}],
}
},
computed: {
listElementShow() {
return this.listElement.filter(e => e.isShow);
}
}
methods: {
toggleElement(index) {
this.listElement[index].isShow = !this.listElement[index].isShow;
}
}
You can do something like this:
<template>
<ul class="list-with-hidden-items">
<li
v-for="item in list"
:key="item.id"
#click="showHide(item.id)"
>
{{ item.text }}
</li>
</ul>
</template>
<script>
export default {
data: () => ({
hidden: {}
}),
methods: {
showHide(id) {
this.$set(this.hidden, id, !this.hidden[id]);
}
}
}
</script>
and then you can render where you want your item to be shown like this:
<div v-if="!this.hidden.item1">I am shown because of item1 is not hidden</div>
To elaborate on some of these answers, you want to keep track of what's hidden and not hidden in your data object using a isHidden flag or similar.
Then when you loop through your object using v-for, conditionally set the isHidden property for the current item when it's clicked.
new Vue({
el: "#app",
data: {
itemList: [{
"id": 1,
"text": "first item",
"isHidden": false
},
{
"id": 2,
"text": "second item",
"isHidden": true,
},
{
"id": 3,
"text": "third item",
"isHidden": false,
},
],
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<ul>
<li v-for="item in itemList" :key="item.id">
<button #click="item.isHidden = !item.isHidden">
<span v-if="item.isHidden">Show</span>
<span v-else>Hide</span>
</button>
<span v-if="!item.isHidden">{{ item.text }}</span>
</li>
</ul>
</div>
You can use a dynamically bound classObject to do such a thing.
See Class and Style Bindings
Sandbox
<template>
<div #click="showHide()" :class="{ isHidden: isHidden }">
<p>This is a thing</p>
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
isHidden: false,
};
},
methods: {
showHide() {
this.isHidden = !this.isHidden;
},
},
};
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.isHidden {
background-color: grey;
}
div {
background-color: #fff;
}
</style>

VueJs set active class, when one li element clicked in v-for loop

I can't figure out how to properly select (set active class) when I do v-for loop and one class is already selected. Let me share the code and with further explanation
These are my available subscriptions and one is already selected, based on user data
<ul>
<li v-for="(s, key, index) in subscriptions"
:class="checkIfClassActive(s.subscription_key)"
#click="setActive(key, index)">
{{ s.name }}
</li>
</ul>
and my js code
checkIfClassActive(userSubscriptionKey) {
if (userSubscriptionKey === this.userSubscription.subscription_key) {
return 'active';
}
},
setActive(key, index) {
},
And this is how is displayed
Now the next step is when I click on one li element it should become active and all other li elements should lose active class, but the problem is that I can't figure out how to properly write setActive function. Can you please help me out, how to do this.
If you need any additional informations, let me know and I will provide. Thank you!
Add a data property called activeIndex:
data() {
return {
activeIndex: undefined
}
},
and your setActive method:
methods: {
setActive(subscription, index) {
this.activeIndex = index;
this.userSubscription.subscription_key = subscription.subscription_key
},
getSubscriptions() {
.....
// fetch subscriptions in this.subscriptions var
.....
// select preselected subscription, when fetching subscriptions
let userSubscriptionKey = this.userSubscription.subscription_key;
let indexOfObject = this.subscriptions.findIndex(
o => o.subscription_key === userSubscriptionKey
);
this.setActive(this.userSubscription, indexOfObject);
}
}
with a slight modification to your template:
<ul>
<li v-for="(s, index) in subscriptions"
:class="{ 'active': activeIndex === index }" :key="s.id"
#click="setActive(s, index)">
{{ s.name }}
</li>
</ul>
You basically set an index that should be active and that's it. active css class is added when list element's index is the same as activeIndex.
As for setting activeIndex to existing choice before the user changes it, you can set activeIndex when fetching subscriptions data to user's current subscription.
Fiddle: http://jsfiddle.net/eywraw8t/256701/
Change your this.userSubscription.subscription_key variable everytime a tab is selected. For this pass it through setActive(s.subscription_key)
You can do something like this,
<li v-for="(s, key, index) in subscriptions"
:class="checkIfClassActive(s.subscription_key)"
#click="setActive(s.subscription_key)">
{{ s.name }}
</li>
Js
checkIfClassActive(userSubscriptionKey) {
if (userSubscriptionKey === this.userSubscription.subscription_key) {
return 'active';
}
},
setActive(subscription_key) {
this.userSubscription.subscription_key=subscription_key;
},
A simple example showing the logic:
html part:
<div id="app">
<ul>
<li
v-for="item in items"
:key="item.id"
:class="item.class"
#click="set_active_id(item.id)"
>{{ item.text }}</li>
</ul>
</div>
Js part:
new Vue({
el: "#app",
data: {
items: [
{ id: 1, text: 'text1', class: 'active' }, //default active
{ id: 2, text: 'text2', class: '' },
{ id: 3, text: 'text3', class: '' }
],
previous_active_id: 1
},
methods: {
set_active_id(id) {
if (this.previous_active_id === id) return //no need to go further
this.items.find(item => item.id === this.previous_active_id).class = '' //remove the active class from old active li
this.items.find(item => item.id === id).class = 'active' //set active class to new li
this.previous_active_id = id //store the new active li id
}
}
})
See it in action
this is quicly
if you use v-for:
<template>
<div>
<ul>
<li
class="anyThings"
v-for="cat in cats"
:key="cat.index"
#click="itemActive(cat.index)"
:class="[(itemA == cat.index) ? 'active':'']"
>{{ cat.yourObjectKey }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
itemA:'0' // for first load and in curent path
}
},
computed: {
cats() {
...
}
},
methods: {
itemActive(e) {
this.itemA = e;
}
},
}
</script>
<style>
.active {
...
}
</style>
if you don't need use v-for and use router-link in element:
<template>
<div>
<ul>
<li #click="itemActive($route.path)">
<router-link to="/" class="anyThings"
:class="[(itemA == '/') ? 'active':'']"
>your text
</router-link>
</li>
<li #click="itemActive($route.path)">
<router-link to="/article" class="anyThings"
:class="[(itemA == '/article') ? 'active':'']"
>your text
</router-link>
</li>
.
.
.
</ul>
</div>
</template>
<script>
export default {
data() {
return {
itemA:this.$route.path // for first load and in curent path
}
},
methods: {
itemActive(e) {
this.itemA = e;
}
},
}
</script>
<style>
.active {
...
}
</style>
I had this problem the simplest answer is to change the "li" tags to "router-link", then change the default styling of the router-link.
In this case "router-link-active"
<ul>
<router-link v-for="item in items"
:key="item.id"
:to="item.route"
>
{{ s.name }}
</router-link>
</ul>
<style>
.router-link-active{
...
}
</style>

Getting index of a data in an array in VUE js

I want to change the status of Tasks when a particular method is called. But The problem is I cannot get the index of the particular item of the array to change its status.
This is my HTML:
<div class="main" id="my-vue-app">
<ul>
<li v-for="task in completeTask">
{{ task.description }} <button #click="markIncomplete">Mark as Incomplete</button>
</li>
</ul>
<ul>
<li v-for="task in incompleteTask">
{{ task.description }} <button #click="markComplete">Mark as Complete</button>
</li>
</ul>
</div>
And this is my Vue:
<script>
new Vue(
{
el: '#my-vue-app',
data:
{
tasks: [
{description:'go to market', status: true},
{description:'buy book', status: true},
{description:'eat biriani', status: true},
{description:'walk half kilo', status: false},
{description:'eat icecream', status: false},
{description:'return to home', status: false}
]
},
computed:
{
incompleteTask()
{
return this.tasks.filter(task => ! task.status);
},
completeTask()
{
return this.tasks.filter(task => task.status);
}
},
methods:
{
markComplete()
{
return this.task.status = true;
},
markIncomplete()
{
return this.task.status = false;
}
}
}
)
</script>
I need make use of markComplete() and markIncomplete() but the problem is I couldn't find the way to get the index of current element to change its status.
You could get the index by declaring a second argument at the v-for:
<li v-for="(task, index) in incompleteTask">
{{ task.description }} <button #click="markComplete(index)">Mark as Complete</button>
</li>
methods:
{
markComplete(index)
{
return this.tasks[index].status = true;
},
But a, maybe simpler, alternative is to simply **pass the `task` as argument**:
<li v-for="task in incompleteTask">
{{ task.description }} <button #click="markComplete(task)">Mark as Complete</button>
</li>
methods:
{
markComplete(task)
{
return task.status = true;
},
RTFM:
You can use the v-repeat directive to repeat a template element
based on an Array of objects on the ViewModel. For every object in the
Array, the directive will create a child Vue instance using that
object as its $data object. These child instances inherit all data
on the parent, so in the repeated element you have access to
properties on both the repeated instance and the parent instance. In
addition, you get access to the $index property, which will be the
corresponding Array index of the rendered instance.
var demo = new Vue({
el: '#demo',
data: {
parentMsg: 'Hello',
items: [
{ childMsg: 'Foo' },
{ childMsg: 'Bar' }
]
}
})
<script src="https://unpkg.com/vue#0.12.16/dist/vue.min.js"></script>
<ul id="demo">
<li v-repeat="items" class="item-{{$index}}">
{{$index}} - {{parentMsg}} {{childMsg}}
</li>
</ul>
Source:
https://012.vuejs.org/guide/list.html
Note: The directive v-repeat is available in old versions of Vue.js :-)

how to add or remove class in vuejs 2 based on id

I want to add or remove class to an element based on id using vuejs, but this code applies the behaviour to all elements. How can I add/remove a class to the element by id? Thanks all in advance.
new Vue({
el:"#test",
data: {
msg: 'msg goes here',
isActive: false
},
methods: {
log: function(e) {
this.isActive = ! this.isActive
//alert(e.currentTarget.id);
}
}
});
.active {
background: red
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="test">
<div id="1" v-on:click="log($event)" v-bind:class="{ active: isActive }">
{{ msg }}
</div>
<div id="2" v-on:click="log($event)" v-bind:class="{ active: isActive }">
{{ msg }}
</div>
</div>
Here is an example of using components to achieve the behavior you are looking for:
// register
const clickable = Vue.component('clickable', {
props: ['msg'],
data: function() {
return {
isActive: false
}
},
template: '<div :class="{ active: isActive }" #click="isActive = !isActive">{{ msg }}</div>'
})
new Vue({
el: "#test",
components: {
clickable
},
data: function() {
return {
msg: 'msg goes here',
isActive: false
}
}
});
.active {
background: red
}
<script src="https://cdn.jsdelivr.net/npm/vue#2.5.13/dist/vue.js"></script>
<div id="test">
<clickable :msg='msg'></clickable>
<clickable :msg='msg'></clickable>
</div>
You have not internalized basic vuejs concepts.
https://v2.vuejs.org/v2/guide/components.html
Both of your elements should be separate components.

Categories