Vue updates all button text after changing specific button - javascript

Hi everyone I'm playing around with Vue JS but for some how I cannot get what I expected. Below are my code.
Template
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="x in count" :key="x">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
#click="test(item.title)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>
Vue
new Vue({
el: '#app',
data: () => ({
name: 'default',
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 2' }
],
count: 10
}),
methods: {
test(title) {
this.name = title
}
}
})
What I want is that when I change a specific button text the other buttons should not be affected. But it seems my code is doing the opposite. What am I missing here? Any help, explanation would be much appreciated. Thanks
new Vue({
el: '#app',
data: () => ({
name: 'default',
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 2' }
],
count: 10
}),
methods: {
test(title) {
this.name = title
}
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.3/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.3/dist/vuetify.min.css">
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="x in count" :key="x">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, index) in items"
:key="index"
#click="test(item.title)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>

You are iterating over a normal number, in your example 10, so you are just showing 10 times the same variable name.
If you now change that variable name to something, it will change in all the buttons accordingly.
You need some way to save the different names, e.g. an array of objects like your items with all the titles.
I took your code and changed it a bit. Instead of iterating over a fixed count, I created an array of names and iterate over that array. When you click one of the buttons and change the text, instead of just changing the universal name attribute - you change the name at the position in the array.
new Vue({
el: '#app',
data: () => ({
names: [
{name: 'default 1'}, {name: 'default 2'}, {name: 'default 3'}, {name: 'default 4'}],
items: [
{ title: 'Click Me 1' },
{ title: 'Click Me 2' },
{ title: 'Click Me 3' },
{ title: 'Click Me 4' }
],
}),
methods: {
test(title, index) {
this.names[index].name = title
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.5.3/vuetify.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.5.3/vuetify.css.map">
<div id="app">
<v-app id="inspire">
<div class="text-xs-center" v-for="(x, index) in names" :key="'name' + index">
<v-menu offset-y>
<v-btn
slot="activator"
color="primary"
dark
>
{{x.name}}
</v-btn>
<v-list>
<v-list-tile
v-for="(item, i) in items"
:key="'item' + i"
#click="test(item.title, index)"
>
<v-list-tile-title>{{ item.title }}</v-list-tile-title>
</v-list-tile>
</v-list>
</v-menu>
</div>
</v-app>
</div>

Related

Change checkbox icon when checked Vuejs Vuetify

So I am trying to check the checkbox Icon to something more custom, perhaps a different icon, however, I tried a couple different things like pseudo elements with no success. right now what this does is loops through data and displays the name and when checked highlights it based on the css class. What I am trying to do is when check change the checkbox icon.
css
.unchecked{
color: gray;
}
.checked{
background-color: #ffff00;
}
Vuejs Component.
Vue.component('check-list', {
template: `
<v-container>
<v-row >
<v-col >
<v-checkbox
v-for="item in values"
:key="item.id"
:value="item.id"
v-model="selected"
>
<template v-slot:label>
<div :class="selected.includes(item.id) ? 'checked' : 'unchecked'">
{{item.name}}
</div>
</template>
</v-checkbox>
</v-col>
</v-row>
<pre>{{selected}}</pre>
</v-container>
`,
data: function () {
return {
selected: [],
values: [
{id:'1',name:'Name 1'},
{id:'2', name:'Name 2'},
{id:'3', name:'Name 3'},
],
ex4: ['red']
}
},
methods: {
},
})
new Vue({
el: '#components-demo',
vuetify: new Vuetify({
icons: {
iconfont: 'md',
},
}),
data: () => ({
}),
})
#chewie, it is possible to change the checkbox icon in Vuetify, There is a specia prop to handle this
:on-icon="'icon-name'"
:off-icon="'icon-name'"
Please find the full code below
<div id="app">
<v-app id="inspire">
<v-container
class="px-0"
fluid
>
<v-row >
<v-col >
<v-checkbox
:on-icon="'mdi-heart'"
:off-icon="'mdi-home'"
v-for="item in values"
:key="item.id"
:value="item.id"
v-model="selected"
>
<template v-slot:label>
<div :class="selected.includes(item.id) ? 'checked' : 'unchecked'">
{{item.name}}
</div>
</template>
</v-checkbox>
</v-col>
</v-row>
<pre>{{selected}}</pre>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data () {
return {
selected: [],
values: [
{id:'1',name:'Name 1'},
{id:'2', name:'Name 2'},
{id:'3', name:'Name 3'},
],
ex4: ['red']
}
},
})
Please find the working codepen here:
https://codepen.io/chansv/pen/QWdEPvB?editors=1010

Vue Increase and decrease value once (replacing buttons)

I made a component that allows me to add a point for each user only once after button click. I would like to additionally enable the undo of an added point (decreasing the value by 1). When I add a point, I want the button to turn red and change the text to "Delete point".
This should be similar to marking the answers as helpful the stackoverflow (but without a negative point).
I used v-if="user.title !== 'Jason Oner'" to disable adding points for this user.
I have no idea how to solve this problem in this case.
Demo code
HTML:
<div id="app">
<v-app id="inspire">
<v-card
class="mx-auto"
max-width="900"
>
<v-list>
<v-list-item
v-for="user in users"
:key="user.title"
>
<v-list-item-avatar>
<v-img
:alt="`${user.title} avatar`"
:src="user.avatar"
></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title v-text="user.title"></v-list-item-title>
<div class="points" v-text="user.points"></div>
</v-list-item-content>
<v-list-item-icon>
<v-btn
v-if="user.title !== 'Jason Oner'"
color="primary"
#click.once="user.points++"
>
<v-icon left>
mdi-plus
</v-icon>
Add point
</v-btn>
</v-list-item-icon>
</v-list-item>
</v-list>
</v-card>
</v-app>
</div>
JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
users: [
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/1.jpg',
title: 'Jason Oner',
points: 5,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/2.jpg',
title: 'Mike Carlson',
points: 10,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/3.jpg',
title: 'Cindy Baker',
points: 15,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/4.jpg',
title: 'Ali Connors',
points: 20,
},
],
}),
})
Please see if this helps
Codepen Demo
HTML:
<div id="app">
<v-app id="inspire">
<v-card class="mx-auto" max-width="900">
<v-list>
<v-list-item v-for="(user,index) in users" :key="user.title">
<v-list-item-avatar>
<v-img :alt="`${user.title} avatar`" :src="user.avatar"></v-img>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title v-text="user.title"></v-list-item-title>
<div class="points" v-text="user.points"></div>
</v-list-item-content>
<v-list-item-icon>
<div v-if="user.add">
<v-btn v-if="user.title !== 'Jason Oner'" color="primary" #click="aab(index)">
<v-icon left> mdi-plus </v-icon> Add point
</v-btn>
</div>
<div v-else>
<v-btn v-if="user.title !== 'Jason Oner'" color="error" #click="aab(index)">
<v-icon left> mdi-plus </v-icon> Del point
</v-btn>
</div>
</v-list-item-icon>
</v-list-item>
</v-list>
</v-card>
</v-app>
</div>
JS:
new Vue({
el: '#app',
vuetify: new Vuetify(),
methods:{
aab(ii)
{ let uu=this.users[ii];
if(uu.add) { uu.points++;uu.add=false;uu.sub=true }
else{ uu.points--; uu.add=true;uu.sub=false}
}
},
data: () => ({
users: [
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/1.jpg',
title: 'Jason Oner',
points: 5,add:true,sub:false,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/2.jpg',
title: 'Mike Carlson',
points: 10,add:true,sub:false,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/3.jpg',
title: 'Cindy Baker',
points: 15,add:true,sub:false,
},
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/4.jpg',
title: 'Ali Connors',
points: 20,add:true,sub:false,
},
],
}),
})
You would have to store somewhere who the current user (you) have upvoted. Normally this is would be in your case on a user object in the users array. eg
{
avatar: 'https://cdn.vuetifyjs.com/images/lists/4.jpg',
title: 'Ali Connors',
points: 20,
// alternatives:
haveIGivenPoint: false,
usersGivenPoints: [1, 5, 2] // Represents user ids that has given points
points: [1, 5, 2] // Instead of points above as a number, you could count users ids who has given points
// etc... It's up to you how to save this state
},
When you have chosen a way to store what you have voted for, you need to use this info on the button:
<v-list-item-icon>
<v-btn
v-if="!user.haveIGivenPoint"
color="primary"
#click.once="user.points++"
>
<v-icon left>
mdi-plus
</v-icon>
Add point
</v-btn>
<v-btn
v-else
color="red"
#click.once="user.points--"
>
<v-icon left>
mdi-minus
</v-icon>
Undo point
</v-btn>
</v-list-item-icon>

Accessibility on vue.js app - Show div when click Tab Key

I will create a menu with jump marks for accessibility that is only visible when the tab key on the keyboard is clicked.
How can I implement this in Vuetify? is there a way to use something like #click for this?
This is my html code for the menu:
<template>
<div class="m-block-tab-jump-sections" data-module="tab-jump-sections" v-on:click.tab="onClick">
<div class="jump-sections js-sections h-break-in">
<a href="#tab-jump-section--metamenu" class="jump-link" title="" target="" tabindex="50">
zur Top-Navigation
</a>
</div>
</div>
</template>
In order to capture the tab on the entire page, you may need to look at putting the following on the app element:
v-on:keydown.tab='handleTab'
Now you can open a menu or do other actions in the handler.
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
showMenu: false,
clickcount: 0,
items: [
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me' },
{ title: 'Click Me 2' },
],
}),
methods: {
handleTab(event) {
this.showMenu = true;
}
}
})
<div id="app" v-on:keydown.tab='handleTab'>
<v-app id="inspire">
<div class="text-center">
<v-menu offset-y v-model='showMenu'>
<template v-slot:activator="{ on }">
<v-btn
color="primary"
dark
v-on:focus='handleTab'
>
Dropdown
</v-btn>
</template>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
#click=""
>
<v-list-item-title>{{ item.title }}</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</div>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
<v-text-field></v-text-field>
</v-app>
</div>
Here is a sample:

How to set deactive other group list if one is active on same time in 2nd level of menu lists?

I am working on the Vue.js template and I need to create a menu up to the 3rd level. If I perform active deactivate functionality using v-model then that is working fine but on the 1nd level, not on 2nd level.
Dom:
<template v-for="item of category">
<template v-if="item.items!= null">
<v-list-group :key="item.title" no-action v-model="item.active">
<template v-slot:activator>
<i class="mr-2" :class="item.action"></i>
<span>{{ item.title }}</span>
</template>
<div>
<template v-for="child in item.items">
<template v-if="child.subitems !== null">
<v-list-group sub-group no-action :key="child.id" prepend-icon="m"
v-model="child.subactive">
<template v-slot:activator>
<v-list-item-title v-text="child.title">
<i class="mr-2" :class="child.action"></i>
</v-list-item-title>
</template>
<template v-for="(subchild) in child.subitems">
<v-list-item :key="subchild.id"
:to="subchild.path">
<v-list-item-title v-text="subchild.title"></v-list-item-title>
</v-list-item>
</template>
</v-list-group>
</template>
</tempalte>
</div>
</v-list-group>
</template>
</template>
Data:
export const category = [
{
action: 'icon-name',
title: 'Level 1',
active: false,
items: [
{
title: 'Level 2',
subactive: true,
path:null,
subitems:[
{ title: 'Level 3', path: '/default/level3'},
{ title: 'Level 3.1', path: '/dashboard/level3.1'}
]
},
{
title: 'Level 2.1',
subactive: false,
path:null,
subitems:[
{ title: 'Level 3', path: '/dashboard/level3'},
{ title: 'Level 3.1', path: '/dashboard/level3.1'},
]
},
]
}
]
}
According to the documentation of vuetify for the 1st level I use v-model="item.active" and I tried same thing with 2nd level v-model="child.subactive" but it is not working for the 2nd level how can I do this??
This issue is due to v-slot:activator in the nested level, few of the components like tooltip, dialog, supports predefined objects to pass to activators and bind to events
Here is the perfect explanation
Find the Vuetify implementation
Tried the same approach to utilize the vuetify behaviour, but nothing worked as expected
Finally ended up with adding some manual code and control the active and deactive of the list groups
Here is the working codepen:
https://codepen.io/chansv/pen/OJJbNjm?editors=1010
Full code:
<div id="app">
<v-app id="inspire">
<v-card class="mx-auto" max-width="500">
<template v-for="item of category">
<template v-if="item.items!= null">
<v-list-group :key="item.title" no-action v-model="item.active">
<template v-slot:activator>
<i class="mr-2" :class="item.action"></i>
<span>{{ item.title }}</span>
</template>
<template v-for="(child, index) in item.items">
<template v-if="child.subitems !== null">
<v-list-group sub-group no-action :key="child.id" v-model="child.subactive" #click="closeOther(index, item.items)">
<template v-slot:activator>
<v-list-item>
<v-list-item-content>
<v-list-item-title>
{{ child.title }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</template>
<v-list-item v-for="(subchild) in child.subitems" :key="subchild.id" #click="navigateTo(subchild.path)">
<v-list-item-action v-if="subchild.icon">
<v-icon>{{ subchild.icon }}</v-icon>
</v-list-item-action>
<v-list-item-content>
<v-list-item-title>
{{ subchild.title }}
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</v-list-group>
</template>
</template>
</v-list-group>
</template>
</template>
</v-card>
</v-app>
</div>
new Vue({
el: '#app',
vuetify: new Vuetify(),
data: () => ({
category: [
{
action: 'icon-name',
title: 'Level 1',
active: false,
items: [
{
title: 'Level 2',
subactive: true,
path:null,
subitems:[
{ title: 'Level 3', path: '/default/level3', icon: 'call_made'},
{ title: 'Level 3.1', path: '/dashboard/level3.1', icon: 'call_made'}
]
},
{
title: 'Level 2.1',
subactive: false,
path:null,
subitems:[
{ title: 'Level 3', path: '/dashboard/level3', icon: 'call_made'},
{ title: 'Level 3.1', path: '/dashboard/level3.1', icon: 'call_made'},
]
},
]
},
],
model: 1,
}),
methods: {
navigateTo(path) {
console.log(path);
// this.$router.push({path: path});
},
closeOther(val, items) {
items.forEach((x, i) => {
if(val != i) x.subactive = false
})
},
}
})

Implementing Vue draggable

i am trying to implement vue draggable and it almost seems to work except for when i try to implement it on a button. It gives me an error message whenever i try to move the button.
Here is an example : https://codepen.io/anon/pen/xoQRMV?editors=1111
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center>
<v-flex>
<draggable v-model="myArray" :options="options" handle=".handle">
<div v-for="element in myArray" :key="element.id" class="title
mb-3">{{element.name}}
<v-icon color="red" class="handle mt-0">drag_handle</v-icon>
</div>
<v-btn class="ml-0">Button</v-btn>
<v-icon color="red" class="handle">drag_handle</v-icon>
</draggable>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
data() {
return {
myArray: [
{name: 'Text1!!!!', id: 0},
{name: 'Text2!!!!', id: 1},
],
options: {
handle: '.handle'
}
}
}
})
Any help is appreciated.
It would have to work from a single array I think, e.g.
https://codepen.io/anon/pen/agQVvm?editors=1111
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout justify-center>
<v-flex>
<draggable :list="combinedArray" :options="options" handle=".handle">
<div v-for="element in combinedArray" :key="element.id" class="title mb-3">
<div v-if="element.type !== 'button'" class="title mb-3">
{{ element.name }}
<v-icon color="red" class="handle mt-0">drag_handle</v-icon>
</div>
<div v-else>
<v-btn>{{ element.name }}</v-btn>
<v-icon color="red" class="handle mt-0">drag_handle</v-icon>
</div>
</div>
</draggable>
</v-flex>
</v-layout>
</v-container>
</v-app>
</div>
new Vue({
el: '#app',
created () {
this.combinedArray = [...this.myArray, ...this.buttonsArray]
},
data () {
return {
myArray: [
{ name: 'Text1!!!!', id: 0 },
{ name: 'Text2!!!!', id: 1 }
],
buttonsArray: [
{ name: 'Button1', id: 2, type: 'button' },
{ name: 'Button2', id: 3, type: 'button' }
],
combinedArray: [],
options: {
handle: '.handle'
}
}
}
})
I was able to implement the drag on buttons by creating their own array:-
<draggable class="list-group" :list="buttonArray" :options="options"
handle=".handle" group="drags">
<div v-for="item in buttonArray" :key="item.id">
<v-btn class="ml-0">{{item.name}}</v-btn>
<v-icon color="red" class="handle">drag_handle</v-icon>
</div>
</draggable>
buttonArray: [
{name: 'Button1', id: 2},
{name:'Button2', id:3}
],
The updated pen:- https://codepen.io/anon/pen/xoQRMV?editors=1111
However it creates an issue where i am not able to replace the text with the button. :(

Categories

Resources