I am trying to listen inside a vue ponent to a window property change, I am not sure this is possible.
The use is for a loader, baiscally I have a file which has an interceptor which alters the "loading" property on the window object (window.loading = true
when request initiated, window.loading = false
when request plete (or error)) (I have issues accessing my store inside the interceptor).
The vue ponent looks like this:
<template>
<v-progress-linear //this is the loader element
height="20"
v-show="loading"
>
</v-progress-linear>
...
puted: {
loading(){
return window.loading}
}
I also tried this as a solution:
created () {
window.addEventListener('loading', this.handleLoading);
},
destroyed () {
window.removeEventListener('loading', this.handleLoading);
},
methods: {
handleLoading(val){
console.log(val)
this.loading = val
}
},
The question is how can I listen on my window.loading
EDIT
Here is the file which contains the interceptor code, note this does not have access to the vue instance.
import axios from 'axios';
import { Utils } from 'em-mon-vue';
import {UsersApi} from "./usersApi";
import {PartnersApi} from "./partnersApi";
import {TrialsApi} from "./trialsApi";
export function apiFactory($security) {
const $http = axios.create({
baseURL: process.env.VUE_APP_API_URL
});
$http.interceptors.request.use(function (config) {
window.loading = true
const token = $security.loginFrame.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, function (error) {
window.loading = true
Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
window.loading = false
return Promise.reject(error);
}
);
$http.interceptors.response.use(function (response) {
window.loading = false
return response;
}, function (error) {
if (error.response && error.response.status === 401) {
Utils.EventBus.$emit('authErr', error);
} else if (error.response && error.response.status === 403) {
alert('You are not authorized to access this application. If you believe you are seeing this message in error, please contact [email protected].');
}
else if (error.response && error.response.status !== 409){
Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
}
else if (error.response && error.response.status === 500){
Utils.EventBus.$emit('toastMessageHandler', {message: 'There was a problem with this operation - please contact [email protected].', type: 'error'});
}
window.loading = false
return Promise.reject({error});
});
const $api = {
users: new UsersApi($http),
partners: new PartnersApi($http),
trials: new TrialsApi($http)
};
return $api;
}
// register $api as vue plugin
export function apiPluginFactory($api) {
return {
install(vue) {
vue.prototype.$api = $api;
},
};
}
Here is the file which has factory function which creates the store:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import {usersStoreFactory} from "./users/module";
// global
import {InitActions} from './actions';
import mutations from './mutations'
import getters from "./getters";
export function storeFactory($api, $config) {
// global
const actions = InitActions($api);
const store = new Vuex.Store({
modules: {
users: usersStoreFactory($api, $config),
},
state: {
partners: null,
// loading: window.loading
},
actions,
mutations,
getters
});
return store;
}
I am trying to listen inside a vue ponent to a window property change, I am not sure this is possible.
The use is for a loader, baiscally I have a file which has an interceptor which alters the "loading" property on the window object (window.loading = true
when request initiated, window.loading = false
when request plete (or error)) (I have issues accessing my store inside the interceptor).
The vue ponent looks like this:
<template>
<v-progress-linear //this is the loader element
height="20"
v-show="loading"
>
</v-progress-linear>
...
puted: {
loading(){
return window.loading}
}
I also tried this as a solution:
created () {
window.addEventListener('loading', this.handleLoading);
},
destroyed () {
window.removeEventListener('loading', this.handleLoading);
},
methods: {
handleLoading(val){
console.log(val)
this.loading = val
}
},
The question is how can I listen on my window.loading
EDIT
Here is the file which contains the interceptor code, note this does not have access to the vue instance.
import axios from 'axios';
import { Utils } from 'em-mon-vue';
import {UsersApi} from "./usersApi";
import {PartnersApi} from "./partnersApi";
import {TrialsApi} from "./trialsApi";
export function apiFactory($security) {
const $http = axios.create({
baseURL: process.env.VUE_APP_API_URL
});
$http.interceptors.request.use(function (config) {
window.loading = true
const token = $security.loginFrame.getToken();
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
}, function (error) {
window.loading = true
Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
window.loading = false
return Promise.reject(error);
}
);
$http.interceptors.response.use(function (response) {
window.loading = false
return response;
}, function (error) {
if (error.response && error.response.status === 401) {
Utils.EventBus.$emit('authErr', error);
} else if (error.response && error.response.status === 403) {
alert('You are not authorized to access this application. If you believe you are seeing this message in error, please contact [email protected].');
}
else if (error.response && error.response.status !== 409){
Utils.EventBus.$emit('toastMessageHandler', {message: error.message, type: 'error'});
}
else if (error.response && error.response.status === 500){
Utils.EventBus.$emit('toastMessageHandler', {message: 'There was a problem with this operation - please contact [email protected].', type: 'error'});
}
window.loading = false
return Promise.reject({error});
});
const $api = {
users: new UsersApi($http),
partners: new PartnersApi($http),
trials: new TrialsApi($http)
};
return $api;
}
// register $api as vue plugin
export function apiPluginFactory($api) {
return {
install(vue) {
vue.prototype.$api = $api;
},
};
}
Here is the file which has factory function which creates the store:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import {usersStoreFactory} from "./users/module";
// global
import {InitActions} from './actions';
import mutations from './mutations'
import getters from "./getters";
export function storeFactory($api, $config) {
// global
const actions = InitActions($api);
const store = new Vuex.Store({
modules: {
users: usersStoreFactory($api, $config),
},
state: {
partners: null,
// loading: window.loading
},
actions,
mutations,
getters
});
return store;
}
Share
Improve this question
edited Jun 20, 2020 at 9:12
CommunityBot
11 silver badge
asked Aug 27, 2019 at 8:36
MichaelMichael
5,0588 gold badges37 silver badges59 bronze badges
1 Answer
Reset to default 7I really don't think municating the loading state via window.loading
is a good idea. Using something like the Vuex store or a similar singleton to hold the loading state seems like a much better approach but that has been (somewhat cryptically) ruled out in the question.
However, assuming that window.loading
is the only option...
Defining a getter and setter for window.loading
might be one way to get that approach to work. There are several ways that might be done but in my example I've chosen to proxy through to a Vue observable to hold the value.
const loadingMonitor = Vue.observable({
loading: false
})
Object.defineProperty(window, 'loading', {
get () {
return loadingMonitor.loading
},
set (loading) {
loadingMonitor.loading = loading
}
})
new Vue({
el: '#app',
puted: {
loading () {
return window.loading
}
},
methods: {
toggle () {
window.loading = !window.loading
}
}
})
<script src="https://unpkg./[email protected]/dist/vue.js"></script>
<div id="app">
<p>{{ loading }}</p>
<button @click="toggle">Toggle</button>
</div>
Note that Vue.observable
was added in Vue 2.6 so if you're using an older version you'd need to use the data
of a new Vue instance to achieve the same effect.
As the value is held in an observable object it can take part in the reactivity system just like everything else. That allows it to be used in a puted property as a reactive dependency.