I am trying to figure out how to have my dynamically generated buttons inside a for loop each have a separate loader. Vuetify has buttons with Loaders.
The problem I am having is, When these buttons are in a for loop and one is clicked they all show the loading indicator. I would like only the one that is clicked to show the loading indicator.
HTML:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading"
@click="loader = 'loading'"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
SCRIPT
data () {
return {
loader: null,
loading: false
}
},
Let's say I have 3 items. The code above will generate three buttons but they all will share the same loading param. How can I have each button use its only loading param? As always any and all help is much appreciated.
I am trying to figure out how to have my dynamically generated buttons inside a for loop each have a separate loader. Vuetify has buttons with Loaders.
The problem I am having is, When these buttons are in a for loop and one is clicked they all show the loading indicator. I would like only the one that is clicked to show the loading indicator.
HTML:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading"
@click="loader = 'loading'"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
SCRIPT
data () {
return {
loader: null,
loading: false
}
},
Let's say I have 3 items. The code above will generate three buttons but they all will share the same loading param. How can I have each button use its only loading param? As always any and all help is much appreciated.
Share Improve this question edited Jun 12, 2020 at 8:28 Boussadjra Brahim 1 asked Aug 22, 2019 at 22:07 JasonJason 1,1515 gold badges20 silver badges43 bronze badges 2-
there a typo here
v-for="(item, i) in items :key='i'"
which should bev-for="(item, i) in items" :key='i'
– Boussadjra Brahim Commented Aug 22, 2019 at 22:17 - 1 fixed the typo, thx – Jason Commented Aug 22, 2019 at 22:18
3 Answers
Reset to default 10You're using the same data property for all buttons, so these buttons share the same loading
state which affects the at one time, to make difference try to add a data property called index
which represents the current clicked button index :
data () {
return {
index:-1,
loader: null,
loading: false
}
},
and bind loading prop to the condition loading && i==index
and update the current index on click event @click="loader = 'loading';index=i"
:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading && i==index"
@click="loader = 'loading';index=i"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
Its actually a lot easier than you think:
<div v-for="(item, i) in items" :key='i'>
<v-btn
dark
color="pink"
:loading="loading[i]"
@click="loading[i] = true"
>
<v-icon>location_on</v-icon> Lookup
<span slot="loader">locating...</span>
<span slot="loader" class="custom-loader">
<v-icon dark>cached</v-icon>
</span>
</v-btn>
</div>
data () {
return {
loading: {},
}
},
In the beginning loading[index]
will be undefined, so it will be evaluated as false, once you establish its value in the click event it will be evaluated as true, it worked for me, hope it helps.
you can use reactive array to prevent changing the index like this.
<div v-for="(item, i) in items" :key='i'>
<v-btn @click.prevent="testload(i)" :loading="loading[i]"></v-btn>
</div>
data () {
return {
loading: [],
}
},
methods: {
testload: function (index) {
// reactive array
this.$set(this.loading, index, true);
console.log(index)
console.log(this.loading[index])
// stop loading after x miliseconds
setTimeout(() => (this.$set(this.loading, index, false)), 3000)
},
dont forget to input false according the length of items, this is the example:
getDataAll: function () {
var i = 0
for (i = 0; i < items.length; i++) {
this.loading.push(false);
}
}