On my page, I have an "edit" button on my page, when I click on it I can edit few things and then save or close without saving.
I want to add a loading bar (like the page is loading) when the user clicks on the "save" button before showing the result.
What I have now is :
the user clicks on the "edit" button, some data become editable and he gets a "save" and a "close" button (that closes without saving), if he clicks on the "save" button the page will reload with the edited data and a notification message "updated" is shown (or an error message if the update didn’t go through).
What I would like to have :
when the user clicks on the "save" button after making his edits, the page will show a loading bar (as to show it’s loading the data) for a few seconds (let’s say for example 5 seconds, if the request is done by that time, the loading will end but if the request isn’t done yet, the bar will keep loading until it’s done) before showing all the data again and the "updated" notification.
Here’s some of the code I have related to this:
My buttons:
<v-col cols="3">
<v-btn
v-if="editGroup"
light
class="mx-2"
@click="editGroup = false"
>
<v-icon left>mdi-close</v-icon>
Close
</v-btn>
<v-btn
v-if="editGroup"
light
class="mx-2"
@click="clickSave"
>
<v-icon left>mdi-content-save</v-icon>
Save
</v-btn>
<v-btn
v-if="
canShowButton(['administrateur', 'configurateur']) &&
!editGroup
"
light
class="mx-2"
@click="editGroup = true"
>
<v-icon left>mdi-pencil</v-icon>
Edit
</v-btn>
</v-col>
And my edit fuction :
async clickSave() {
this.editGroup = false
this.loading = true
let uri = this.endpointPrefix + '/groups/' + this.groupid
let dat = {
name: this.groupDataEdited.name,
description: this.groupDataEdited.description,
idTariff: this.groupDataEdited.idTariff,
idEvseToAdd: [],
}
await this.$axios.$put(uri, dat)
.then(() => {
this.$nuxt.$emit('show-notification', {
text: 'updated',
color: 'green',
})
this.loadData(this.groupid)
})
.catch((error) => {
this.$nuxt.$emit('show-notification', {
text:
'could not be updated !' +
error.response.data,
color: 'red',
})
})
.finally(() => (this.loading = false))
setTimeout(() => {
this.loading = false
}, 5000);
},
As for the progress bar, I am using vuetify progress circular like this :
<v-progress-circular
v-show="loading"
indeterminate
color="primary">
</v-progress-circular>
But I still haven’t figured out at what point of my code should I put this component yet to have it shown in all of my page, I tried putting it before the buttons but it doesn’t work at all (nothing happens) and if I put it inside the buttons it keeps loading forever.
2
Answers
This is what state management such as pinia is for. If you set up a pinia store like so:
Then, instead of doing all the data work in your vue script, you just do this part:
Then your main, overarching page view can access the same store, watch that variable, and change according to show whatever you need.
Your best bet is going to probably be to put in an overlay, which can be placed at the very bottom of your root element.
As a rough example:
The overlay will cover the entire screen until the loading prop is marked as false
https://vuetifyjs.com/en/components/overlays/
Edit:
Additionally, loading will have to be set in the data section of your page when you first load in.