How to render dynamic elements in VueJS? - javascript

I am trying to create an app where users can select what kind of vuetify element they would like to render on the page? So I have 4 options that users can select from. I want to render the respective vuetify component on click, so if the user selects divider a <v-divider> </v-divider> should render, for a spacer, a <v-spacer></v-spacer> and for a toolbar a <v-toolbar></v-toolbar> and if they select text then a <v-btn></v-btn> with text would be displayed. I am really stuck on how I can do it.
This is a sample codepen
new Vue({
el: "#app",
data() {
return {
elements: [{
title: "Divider",
value: "divider"
},
{
title: "Spacer",
value: "spacer"
},
{
title: "Toolbar",
value: "toolbar"
},
{
title: "Text",
value: "text"
}
],
selected: []
};
},
methods: {
renderElements() {
console.log(this.selected);
this.selected = [];
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout column>
<v-flex v-for="el in elements" :key="el.value">
<v-checkbox :value="el.value" v-model="selected" :label="el.title"></v-checkbox>
</v-flex>
<v-btn #click="renderElements"> Render Dynamic Elements</v-btn>
</v-layout>
</v-container>
</v-app>
</div>
I would really appreciate some help with this.

It seems you need to use dynamic components:
<component v-for="(el, i) in selected" :key="i" :is="el.value"></component>
new Vue({
el: "#app",
data() {
return {
elements: [
{
title: "Divider",
value: "v-divider"
},
{
title: "Spacer",
value: "v-spacer"
},
{
title: "Toolbar",
value: "v-toolbar"
},
{
title: "Text",
value: "v-btn"
}
],
selected: []
};
},
methods: {
renderElements() {
console.log(this.selected);
this.selected = [];
}
}
});
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout column>
<v-flex v-for="el in elements" :key="el.value">
<v-checkbox :value="el" v-model="selected" :label="el.title">
</v-checkbox>
</v-flex>
<v-btn #click="renderElements"> Render Dynamic Elements</v-btn>
<component v-for="(el, i) in selected" :key="i" :is="el.value"></component>
</v-layout>
</v-container>
</v-app>
</div>

new Vue({
el: "#app",
data() {
return {
elements: [
{
title: "Divider",
value: "v-divider",
show: false
},
{
title: "Spacer",
value: "v-spacer",
show: false
},
{
title: "Toolbar",
value: "v-toolbar",
show: false
},
{
title: "Text",
value: "v-btn",
show: false
}
],
selected: []
};
},
methods: {
renderElements() {
console.log(this.selected);
for(let i=0; i<this.elements.length; i++)
{
this.elements[i].show = this.selected.includes(i);
}
}
}
});
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.14/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container>
<v-layout column>
<v-checkbox v-for="(item, i) in elements"
:key="i"
:label="item.title"
:value="i"
v-model="selected"
></v-checkbox>
<v-btn #click="renderElements"> Render Dynamic Elements</v-btn>
<component v-for="(item, i) in elements" :key="i + 10" :is="item.value" v-if="item.show">{{ item.title }}</component>
</v-layout>
</v-container>
</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

get v-select text on select

I saw some documentation on v-select and slots, but didn't really understand if I can apply it for my example codepen.
I just need to get the selected text (not the value), and use it somewhere in the code:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
state: {},
selectedText: "",
states: [
{ value: "a", text: "alpha" },
{ value: "b", text: "beta" },
{ value: "g", text: "gamma" }
]
},
methods: {
change: (newValue) => {
// do something with the text
// "alpha", "beta", or "gama"
console.log(newValue);
}
}
});
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<label>my selected text is: {{state}}</label>
<v-row align="center">
<v-col cols="3">
<v-select v-model="state" :items="states" #change="change" :text="selectedText"></v-select>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
You need to add return-object prop to <v-select>
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
state: null,
selectedText: "",
states: [
{ value: "a", text: "alpha" },
{ value: "b", text: "beta" },
{ value: "g", text: "gamma" }
]
},
methods: {
change: (newValue) => {
// do something with the text
// "alpha", "beta", or "gama"
console.log(newValue.text);
}
}
});
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet"/>
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.js"></script>
<div id="app">
<v-app id="inspire">
<v-container fluid>
<label>my selected text is: {{state && state.text}}</label>
<v-row align="center">
<v-col cols="3">
<v-select :items="states" v-model="state" #change="change" item-text="text" return-object></v-select>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
Edit:
Ok so based on your approach, the solution would be to use the country code to find appropriate country object in the country list and set that.
Here is how you would solve it:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
country: "c",
countries: [{
code: "a",
name: "Ameriga Fatela"
},
{
code: "b",
name: "Bolivia Grande"
},
{
code: "c",
name: "Comore Potentia"
}
]
},
methods: {
getCountryCode() {
return "b"; // have no c.name here!
},
change() {
var newCode = this.getCountryCode();
// Since we were getting objects when changing options, we must also set objects
this.country = this.countries.filter(country => country.code === newCode)[0];
}
}
});
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-container>
<div>current code is >{{country.code}}<</div>
<div>current name is >{{country.name}}<</div>
<v-row>
<v-col cols="12">
<v-select v-model="country" :items="countries" item-text="name" item-value="code" return-object></v-select>
<v-btn #click="change">change by script to 'b'</v-btn>
</vcol>
</v-row>
</v-container>
</v-app>
</div>
Your states objects contain both value and text properties. If you change value to key v-select recognizes the change and you can access the text property via this.state. Like so:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
state: {},
selectedText: "",
states: [
{ key: "a", text: "alpha" },
{ key: "b", text: "beta" },
{ key: "g", text: "gamma" }
]
},
methods: {
change: (newValue) => {
// do something with the text
// "alpha", "beta", or "gama"
console.log(newValue); // Also returns text attribute instead of key
}
}
});
<div id="app">
<v-app id="inspire">
<v-container fluid>
<label>my selected text is: {{state}}</label>
<v-row align="center">
<v-col cols="3">
<v-select v-model="state" :items="states" #change="change"></v-select>
</v-col>
</v-row>
</v-container>
</v-app>
</div>
EDIT:
The best option I found is to use a computed property for the selected text, without changes to the current code (go in FullPage after lauching the snippet to correctly see the output):
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
countries: [
{ code: "a", name: "Ameriga Fatela" },
{ code: "b", name: "Bolivia Grande" },
{ code: "c", name: "Comore Potentia" }
],
country: "b"
},
methods: {
getCountryCode() {
return "c"; // have no c.name here!
},
change() {
this.country = this.getCountryCode();
}
},
computed: {
countryName() {
return this.countries.find((c) => c.code === this.country).name;
}
}
});
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-container>
<div>current code is >{{country}}<</div>
<div>current name is >{{countryName}}<</div>
<v-row>
<v-col cols="12">
<v-select v-model="country" :items="countries" item-text="name" item-value="code"></v-select>
<v-btn #click="change">change by script to '{{getCountryCode()}}'</v-btn>
</vcol>
</v-row>
</v-container>
</v-app>
</div>
Another option is (Codepen here) the suggestion of Anurag Srivastava to use return-object, I returned the object. However, it have some drawbacks, cause actually I am not able to properly change the value by code:
new Vue({
el: "#app",
vuetify: new Vuetify(),
data: {
country: "c",
countries: [
{ code: "a", name: "Ameriga Fatela" },
{ code: "b", name: "Bolivia Grande" },
{ code: "c", name: "Comore Potentia" }
]
},
methods: {
getCountryCode() {
return "b"; // have no c.name here!
},
change() {
var newCode = this.getCountryCode();
this.country = newCode;
}
}
});
<link href="https://cdn.jsdelivr.net/npm/#mdi/font#4.x/css/materialdesignicons.min.css" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/babel-polyfill/dist/polyfill.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue#2.x/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#2.2.20/dist/vuetify.min.js"></script>
<div id="app">
<v-app>
<v-container>
<div>current code is >{{country.code}}<</div>
<div>current name is >{{country.name}}<</div>
<v-row>
<v-col cols="12">
<v-select v-model="country" :items="countries" item-text="name" item-value="code" return-object></v-select>
<v-btn #click="change">change by script to 'b'</v-btn>
</vcol>
</v-row>
</v-container>
</v-app>
</div>
However, in both cases we should recalculate the country name. That is not good. Imagine to build the combobox we have to do a heavy operation... recalculating it each time is time-consuming and really not optimal....

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. :(

Vue.js dialog/modal closes on parent component

I am trying to open my CanvasPreview Component in another component but it fails,
first, it quickly shows the dialog/modal afterward it gets hidden again if I open the Vue Dev tool
the showCanvasPreview is set to false if I manually edit it in my console to true the modal gets shown.
So I guess that it gets set to false again, but I can't see why.
This is the dialog/modal component:
<template>
<v-dialog
v-model="show"
>
<v-card>
<v-card-actions>
<v-container grid-list-md text-xs-center>
<v-layout row wrap>
</v-layout>
</v-container>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import CanvasPreviewSourceUpload from './CanvasPreviewSourceUpload';
export default {
components: {
'canvas-preview-source-upload': CanvasPreviewSourceUpload
},
props: {
imgSrc: String,
visible: Boolean
},
computed: {
show: {
get () {
return this.visible;
},
set (visible) {
if (!visible) {
this.$emit('closePreview');
}
}
}
},
}
</script>
And in my parent component I call the preview component like this:
<template>
<div>
//... some more html
<div id="canvas-body">
<canvas id="pdf-render"></canvas>
<canvas id="selectCanvas"
#mousedown="markElementOnMouseDown"
#mousemove="updatePreview"
#mouseup="markElementOnMouseUp">
</canvas>
</div>
<canvas-preview
:imgSrc="this.targetImage.src"
:visible="showCanvasPreview"
#closePreview="showCanvasPreview=false">
</canvas-preview>
</div>
</template>
<script>
import CanvasPreview from '#/js/components/CanvasPreview';
export default {
components: {
'canvas-preview': CanvasPreview
},
props: {
'name': String
},
data: () => ({
showCanvasPreview: false,
...
}),
methods: {
markElementOnMouseUp (event) {
this.isDragging = false;
this.targetImage.src = this.clipCanvas.toDataURL();
this.targetImage.style.display = 'block';
this.showCanvasPreview = true;
console.log("mouseup: " + this.showCanvasPreview);
},
}
</script>
Try this one
<v-dialog
v-model="show"
>
<v-card>
<v-card-actions>
<v-container grid-list-md text-xs-center>
<v-layout row wrap>
<canvas-preview-source-upload
:imgSrc="imgSrc"
#close.stop="show=false">
</canvas-preview-source-upload>
</v-layout>
</v-container>
</v-card-actions>
</v-card>
</v-dialog>
</template>
<script>
import CanvasPreviewSourceUpload from './CanvasPreviewSourceUpload';
export default {
components: {
'canvas-preview-source-upload': CanvasPreviewSourceUpload
},
data: ()=> ({
show: false
}),
props: {
imgSrc: String,
visible: Boolean
},
watch: {
show(isShow){
if (!isShow) {
this.$emit('closePreview');
}
}
visible(isVisible) {
this.show = isVisible;
}
}
}
</script>```
Something like this should allow you to open a v-dialog from a separate component..
If you supply a CodePen or CodeSandbox with your code in it, we would be able to better assist you.
[CodePen mirror]
const dialog = {
template: "#dialog",
props: {
value: {
type: Boolean,
required: true
},
},
computed: {
show: {
get() {
return this.value;
},
set(value) {
this.$emit("input", value);
}
}
},
};
const dialogWrapper = {
template: "#dialogWrapper",
components: {
appDialog: dialog,
},
data() {
return {
isShown: false,
}
}
}
new Vue({
el: "#app",
components: {
dialogWrapper
}
});
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vuetify#1.5.6/dist/vuetify.min.js"></script>
<link href="https://fonts.googleapis.com/css?family=Roboto:100,300,400,500,700,900|Material+Icons" rel="stylesheet" />
<link href="https://cdn.jsdelivr.net/npm/vuetify#1.5.6/dist/vuetify.min.css" rel="stylesheet" />
<div id="app">
<v-app>
<v-content>
<dialog-wrapper/>
</v-content>
</v-app>
</div>
<script type="text/x-template" id="dialog">
<v-dialog v-model="show">
<v-card>
<v-card-actions pa-0>
<v-spacer/>
<v-btn dark small color="red" #click="show = false">Close</v-btn>
<v-spacer/>
</v-card-actions>
<v-card-title class="justify-center">
<h2>
Hello from the child dialog
</h2>
</v-card-title>
</v-card>
</v-dialog>
</script>
<script type="text/x-template" id="dialogWrapper">
<div>
<h1 class="text-xs-center">I am the wrapper/parent</h1>
<v-container>
<v-layout justify-center>
<v-btn color="primary" dark #click.stop="isShown = true">
Open Dialog
</v-btn>
</v-layout>
</v-container>
<app-dialog v-model="isShown"></app-dialog>
</div>
</script>

Vue updates all button text after changing specific button

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>

Categories

Resources