I have a simple function that is flipping some variables. (placeholder for the real logic). the issue is that Vue is not updating the dom when a variable is updated until the end of the function. I have tried nextTrick()
with no success.
part of the template:
<div>
<q-icon v-if="status === 'DONE'" name="mdi-check-circle" color="green" size="2em"/>
<q-icon v-if="status === 'PENDING'" name="mdi-checkbox-blank-circle-outline" color="orange-8" size="2em"/>
<q-icon v-if="status === 'FAILED'" name="mdi-alert-circle" color="red-8" class="q-pr-sm" size="2em"/>
<q-spinner-pie v-if="status === 'PROCESSING'" color="primary" size="2em" class="q-pr-sm" />
<span class="text-italic text-caption" >( {{ curTotal }} / {{ itemTotal }} )</span>
</div>
My very simple function:
processImages(){
this.status = 'PROCESSING'
for ( let i = 0; i < this.itemTotal; i++){
this.sleep(1000)
this.curTotal += 1
}
}
Edit
I changed my function to call my api endpoint instead of the sleep()
function.
async processImages(){
this.rows[0].status = 'PROCESSING'
for ( let i = 0; i < this.itemTotal; i++){
const { data } = await $fetch('/api/scrape', {
method: 'GET',
})
this.rows[0].curTotal += 1
}
this.rows[0].created = true
}
The sleep function i was using was:
sleep(miliseconds) {
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()) {
}
}
It was the sleep function that was blocking the ui update.
It appears to work just fine, maybe provide some more code like your sleep
method:
<script>
export default {
data() {
return {
curTotal: 1,
itemTotal: 20,
status: "FAILED"
}
},
methods: {
async sleep(ms) { return new Promise((r) => setTimeout(r, ms)) },
async processImages() {
this.status = 'PROCESSING'
// do what ever
for ( let i = 0; i < this.itemTotal/2; i++){
await this.sleep(1000)
this.curTotal += 1
}
this.status = 'DONE'
},
},
}
</script>
An alternative would be to switch to a composition api and using a ref
for the status
,itemTotal
and curTotal
<script setup>
import { ref } from 'vue'
const status = ref('FAILED')
const curTotal = ref(0)
const itemTotal = ref(20)
const sleep = ms => new Promise((r) => setTimeout(r, ms));
async function processImages() {
status.value = 'PROCESSING'
// do what ever
for ( let i = 0; i < itemTotal.value; i++){
await sleep(1000)
curTotal.value += 1
}
status.value = 'DONE'
}
</script>
<template>
<div>
<span v-if="status === 'FAILED'">FAILED</span>
<span v-if="status === 'PROCESSING'">PROCESSING</span>
<span v-if="status === 'DONE'">DONE</span>
<button @click=processImages>
Trigger
</button>
<span class="text-italic text-caption" >( {{ curTotal }} / {{ itemTotal }} )</span>
</div>
</template>