0

I want to add a loading spinner component, as long as the data from the api has not arrived. I worked before in Vue2 + JavaScript and are super new to Vue3 + TypeScript.

I tried to archive it like that, but fail (different attempts of loading the TheCustomersTable are commented out above loader:)

<script lang="ts">
    import { computed, defineComponent, defineAsyncComponent } from "vue";
    import CustomersModule from "@/store/modules/customers";
    // import TheCustomersTable from "@/components/Elements/customers/TheCustomersTable.vue";
    import LoadingSpinner from "@/components/Elements/LoadingSpinner.vue";
    // import BaseFilter from "@/components/Elements/Filter/BaseFilter.vue";
    
    // LoadingSpinner: (): Promise<defineAsyncComponent> => import('@/components/Elements/LoadingSpinner.vue')
    
    const TheCustomersTable = defineAsyncComponent({
        // loader: (import ("@/components/Elements/Filter/BaseFilter.vue")) /*webpackChunkName: "user" */,
        // loader: import ("@/components/Elements/customers/TheCustomersTable.vue") /*webpackChunkName: "user" */,
// loader: (): Promise<defineAsyncComponent> => import('@/components/Elements/customers/TheCustomersTable.vue'),
        loader: import('@/components/Elements/customers/TheCustomersTable.vue'),
        // loader: TheCustomersTable,
        loadingComponent: LoadingSpinner,
        delay: 2000,
        suspensible: false,
        // errorComponent: ErrorCmp,
        timeout: 3000
    })
    
    export default defineComponent({
      name: "CustomersView",
      components: {
        // LoadingSpinner,
        // BaseFilter,
        TheCustomersTable
      },

Unfortunately I do not find much material, to how to pull that off

1
  • In addition: I tried as well importing "by ... loader: () => import ("@/components/Elements/customers/TheCustomersTable.vue") /*webpackChunkName: "user" */, loadingComponent: () => import ("@/components/Elements/LoadingSpinner.vue") /*webpackChunkName: "user" */," in const CustomerTable. No errors, but no LoadingSpinner either :/ Commented May 25, 2021 at 13:46

1 Answer 1

1

I have handled it better using v-if, this is my code

<template>
  <Banner :currentPage="currentPage" :previousPage="previousPage" />

    <section class="section">
            <div class="container" v-if="!isLoading"> //add v-if !isLoading
               // rest of codes
            </div>
            <div v-else>
                <Loading /> //keep a separate page/Componet that will display when APIs are not ready
            </div>
        </section>
</template>

then in your Javascript

<script>
import Banner from '@/components/Banner.vue'
import SingleJob from '@/components/SingleJob.vue'
import Loading from '@/views/custom/Loading.vue' // include Loading Component 
export default {
  name: 'Jobs',
  emits: ["paginate"],
  components: {
    Banner, SingleJob,
    Loading,
  },
  data(){
      return {
        search: '',
    
        isLoading: true, // isLoading should be true so that your page will start loading first
        jobs: {current_page: 1},
        allJobs: {},
        data: {},
        errors: false,
      }
  },
  methods: {
    getJobs(page){
      if (typeof page === 'undefined') {
        page = 1
      }
      this.isLoading =  true
      axios.get('/jobs?page=' + page).then(response => {
          this.jobs = response.data
      }).catch(errors => {
          this.errors = errors.response.data.errors
      }).finally(() => {   //set this finally it after your Api call
            setTimeout(function () {
                this.isLoading =  false  //set isloading to false
            }.bind(this), 200); //time delay
        })
    },
    
    }
  },

  mounted () {
  this.getJobs()
  this.getFilteredJobs()
  this.getCategories()
  this.getCountries()
}
}
</script>

in Loading component you can put anything that will display when loading. such as picture or animation or you can copy here

<template>
  <div class="loading-wrap">
      <div class="loading">
          <div class="loading-dots"><span class="dot"></span><span class="dot"></span><span class="dot"></span><span class="dot"></span></div>
      </div>
  </div>
</template>

<script>
export default {

}
</script>

<style>
.loading-wrap{
    height: 100vh;
    position: relative;
}
.loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%,-50%);
    text-align: center;
}
.title{
    margin-bottom: 50px;
}

.dot{
    height: 25px;
    width: 25px;
    border-radius: 50%;
    background-color: #bbb;
    display: inline-block;
    animation: blink 1.4s infinite;
}

@keyframes blink {
    0% {
        opacity: 0.2;
    }
    20%{
        opacity: 1;
    }
    80%{
        opacity: 0.4;
    }
    100%{
        opacity: 0.2;
    }
}

.dot:nth-child(1){
    background-color: #156394;
}
.dot:nth-child(2){
    background-color: #8ec73a;
    animation-delay: 0.2s;
}
.dot:nth-child(3){
    background-color: #156394;
    animation-delay: 0.4s;
}
.dot:nth-child(4){
    background-color: #8ec73a;
    animation-delay: 0.6s;
}
</style> 

Best of Luck

Sign up to request clarification or add additional context in comments.

5 Comments

Hi @WillianBabuu, thank you, for your suggestion. In the meanwhile I did it the same way. It works great. But, the vue suggestions looks so neat and clean. I would really like to make use of it. (error component and delay look handy, too). It seems to be connected, that the data comes from the api and uses v-if (or so) Otherweise, would it be possible, to build something like a decorator. So that I do not need to it into each desired component, but just add a little something? Or a vue directive, which passes in a loading and error component and sets v-if at the right place ...?
hi @Ehrlich_Bachman, if i got you well. You mean you could reuse the components right. The Loading components you can use it everywhere You just need to include it. Or maybe i did not get well your comment
Hi @WillianBabuu, yeah, that is what I usually would do. But I thought, since I would want to include it in most components, maybe there is a lessy copy+paste way to do it. On the other hand insert one global, component, might be less hustle then writing a directive or decorator. Thanks for the nice exchange.
@Ehrlich_Bachman for me Registering components would do. You can include component to any page. I too did the same the same loading page is everywhere. Can you also Accept my answer. That would be great too
Yeah, but it does not address, how I can make use of i. e. loadingLomponent or errorComponent. That seems the best work around so far and I used that approach before too, but not how to use that nice looking feature. I try to get down to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.