5

i am creating an application in VueJS and i would like to create a service or global variable which stores if the client is making a request to the server. I have been thinking in configure an interruptor which sets the global variable to true when is making a request, and when the request is finished sets the variable to false.

So when i use a loader component it shows only when the variable is true.

Example:

// As i do
<form @submit.prevent="save">
        <h2>{{ $t('organization.labels.organization')}}</h2>
        <div class="row">
          <div class="col m6 s12" v-if="$route.name == 'organization'"> 
            <form-input-text :title="$t('organization.labels.client_number')" :model.sync="form.client.client_number" ></form-input-text>
          </div>
          <div class="col m6 s12">
            
            <div class="center" v-if="loader.is_loading">
              <material-loader></material-loader>
              <br> <small>{{ $t('organization.labels.loading')}}</small>
            </div>
            
          </div>
        </div>
        
</form>

// As it should work
<form @submit.prevent="save">
        <h2>{{ $t('organization.labels.organization')}}</h2>
        <div class="row">
          <div class="col m6 s12" v-if="$route.name == 'organization'"> 
            <form-input-text :title="$t('organization.labels.client_number')" :model.sync="form.client.client_number" ></form-input-text>
          </div>
          <div class="col m6 s12">
            
            <div class="center" v-if="$loader.is_loading"> <== $loader
              <material-loader></material-loader>
              <br> <small>{{ $t('organization.labels.loading')}}</small>
            </div>
            
          </div>
        </div>
        
</form>

Any idea?? The main idea is to have to create a variable is_loading, for each view to know if the user is requesting for something.

csantana
  • 546
  • 1
  • 8
  • 13

3 Answers3

5

the answer was to create a variable is_loading in the my app.vue which it is the app container ($root).

<template>
  <div id="app">
    <navigation></navigation>
    <div class="main-container">
      <router-view></router-view>
    </div>
    <!-- <binnacle-footer></binnacle-footer> -->
  </div>
</template>

<script>

  import UserProvider from 'users/provider/User.provider'
  import session from 'session/index'
  export default {
    data() {
      return{
        loader : {
          is_loading : false
        }
      }
    },
    methods :{
      getUser(){
        var self = this;
        self.$root.loader.is_loading = true;
        UserProvider.get().then((user)=>{
        self.$root.loader.is_loading = false;
          self.current_user = user;
        }).catch((err)=>{
          self.$root.loader.is_loading = false;
        })
      }
    },
    ready(){
      
      this.getUser();
    },

  }
</script>

and then you must only call it wherever you want by using $root.

:)

csantana
  • 546
  • 1
  • 8
  • 13
2

Have you tried:

window.is_loading = true;

if (window.is_loading) { }

UPDATE per comment:

The scope for that variable is not available to the template. If you can raise an event for start / finish for the ajax response you can handle it outside of your template. Instead of the condition in the template, include it always in the template but set the DIV CSS property to display:none. Then in the event handler for start, set it to display: inline and event handler for response received set it to display:none again.

Steve Seeger
  • 1,409
  • 2
  • 20
  • 25
  • This is a good idea, however, it does not help me, because it must be reactive, if you read the template i want to use v-if="". your answer would not work. :( – csantana Jan 12 '16 at 00:46
  • Ah, reading your question more carefully I see that you want to have a variable set to true/false based on if the connection is active. You mean it should be true after the user submits, and false when the response comes back from the server? – Steve Seeger Jan 12 '16 at 00:53
  • Yes like so,but not connection active, it's when you make a request via Ajax, before ajax request is created i need to set $is_loading = true, and when the ajax request is resolved $is_loading = false, i dont only need a variable as well, i need a reactive variable, i tried to extend it in Vue prototype Using Vue.prototype.$is_loading and it works, however when i render it into the view by using {{ $is_loading }} it's not reactive. :) – csantana Jan 12 '16 at 19:32
0

You can make a VUEX module and name it ajax.js like this:

const state = {
    ajax: {is_loading: false}
};
const mutations = {
    'SET_LOADING' (state, status){
        state.ajax.is_loading = status;
    },
};
const actions = {
    set_loading: ({commit}, status) => {
        commit('SET_LOADING', status);
    },
};
const getters = {
    is_loading: state => {
        return state.ajax.is_loading;
    },
};
export default {
    state,
    mutations,
    actions,
    getters
};

Then you must register it in store.js file.

Now you can use this code globally next to your Vue instance:

import store from "./store/store";
window.axios.interceptors.request.use(function (config) {
    store.state.ajax.ajax.is_loading = true;
    return config;
}, function (error) {
    store.state.ajax.ajax.is_loading = false;
    return Promise.reject(error);
});

axios.interceptors.response.use(function (response) {
    store.state.ajax.ajax.is_loading = false;
    return response;
}, function (error) {
    store.state.ajax.ajax.is_loading = false;
    return Promise.reject(error);
});

I tried to use this code:

store.state.dispatch('set_loading', true);

But it didn't work! so I use another syntax to change the value of is_loading!

Now in your component you can access is_loading variable in this way:

this.$store.getters.is_loading;

or by mapping getteres:

computed:{
    ...mapGetters([
        'is_loading'
    ]),
},
Saeid
  • 1,269
  • 1
  • 9
  • 12