I used a v-if/else statement in my html. These depend on a watcher. In my watcher I also used a setTimeout()
function to clone an api call. When I try to set the isLoading data property to false in my setTimeout() function, the dom is not updated and so the v-if stays true.
Watch:
watch: {
selectedConfederations(newValue) {
alert(newValue.length);
if (newValue.length > 0) {
this.showStepper = false;
this.isLoading = true;
setTimeout(function() {
this.isLoading = false; /* This.isLoading will be false but DOM does not update and v-if stays on true and spinner will still be showing */
}, 3000);
} else {
this.showStepper = true;
this.isLoading = false;
}
},
},
Data:
data() {
return {
showStepper: true,
isLoading: false,
}
}
Html:
<div v-if="isLoading">
<v-layout row justify-center>
<v-progress-circular
:size="70"
:width="7"
color="primary"
indeterminate
></v-progress-circular>
</v-layout>
</div>
<div v-else>
<v-layout row mt-2>
<v-flex xs3>
<v-card style="position:fixed" max-width="400">
<v-toolbar row color="primary" dark>
<v-flex xs4>
<v-toolbar-title>
<v-icon dark>filter_alt</v-icon> Filter</v-toolbar-title
>
</v-flex>
<v-flex xs8 style="padding-left: 50%;">
<v-tooltip bottom>
<template v-slot:activator="{ on, attrs }">
<v-btn
style=""
color="white"
outline
small
fab
v-bind="attrs"
v-on="on"
>
<v-icon dark>autorenew</v-icon>
</v-btn>
</template>
<span>Reset filter</span>
</v-tooltip>
</v-flex>
</v-toolbar>
<v-card-text style="border-bottom: 1px solid lightgrey;">
<v-checkbox
label="Include girls"
color="primary"
hide-details
></v-checkbox>
<v-checkbox
disabled
label="Include professional clubs only"
color="primary"
hide-details
></v-checkbox>
</v-card-text>
<v-card-text style="border-bottom: 1px solid lightgrey;">
<h2 >
Budget of clubs
</h2>
<v-chip
v-for="tag in filterItems.budgets"
:key="tag.id"
@click="() => selectedBudgetOption(tag)"
:outline="tag.selected ? false : true"
color="primary"
>
{{ tag.name }}
</v-chip>
</v-card-text>
<v-card-text style="border-bottom: 1px solid lightgrey;">
<h2 >
Amount of players inside clubs
</h2>
<v-chip
v-for="tag in filterItems.playersizes"
:key="tag.id"
@click="() => selectedBudgetOption(tag)"
:outline="tag.selected ? false : true"
color="primary"
>
{{ tag.name }}
</v-chip>
</v-card-text>
<v-card-text>
<h2 >
Teams available
</h2>
<v-chip
v-for="tag in filterItems.agegroups"
:key="tag.id"
@click="() => selectedBudgetOption(tag)"
:outline="tag.selected ? false : true"
color="primary"
>
{{ tag.name }}
</v-chip>
</v-card-text>
</v-card>
</v-flex>
<v-flex xs9>
<v-layout>
<RadarChart
:name="dimensionChart"
:title="dimensionChartTitle"
/>
</v-layout>
</v-flex>
</v-layout>
<v-layout row>
<v-flex xs3> </v-flex>
<v-flex xs9>
<v-layout>
<RadarChart
:name="internationalStandardChart"
:title="internationalStandardChartTitle"
/>
</v-layout>
</v-flex>
</v-layout>
</div>
I think the problem is that the DOM is not being updated even when the watcher detects changes. The watcher is based on a v-model that is connected to a v-dropdown. All help is welcome and is much appreciated!
CodePudding user response:
The isLoading is never returning to false because this
in your setTimeout function is not referencing to the vue instance but to his own scope.
Making it an arrow function will fix this :
setTimeout(() => {
this.isLoading = false;
}, 3000);
CodePudding user response:
That doesn't work because of this code :
setTimeout(function() {
this.isLoading = false;
}, 3000);
In the code above, the value of this
is different because you used a function
which has a dynamic execution context (this
).
--
To solve this problem you can store the value of this
and then use it in the function :
const that = this
setTimeout(() => {
that.isLoading = false;
}, 3000)
You can also directly bind this
of the method :
setTimeout(function () {
this.isLoading = false;
}.bind(this), 3000)
Finally, the more convenient solution is to use an arrow function (which does not define its own this
):
setTimeout(() => {
this.isLoading = false;
}, 3000)