Tips for enhancing loader methods for optimal use with loading indicator components in Vue

To display loading progress, I've implemented a component with a slot and an enum prop like the following example:

<template>
    <div class="loaded-listing">
        <div class="loaded-listing__loading-placeholder" v-if="isLoading">
            <some-third-party-indicator ... />
        </div>
        <slot v-else />
        <!-- the Failed status is not displayed yet -->
    </div>
</template>

<script lang="ts">

    export enum loadStatusEnum {
        Loading,
        Loaded,
        Failed
    }

    import { Component, Prop, Vue } from 'vue-property-decorator'
    import { SomeThirdPartyIndicator } from 'some-third-party-indicator'

    @Component({
        props: ['loadStatus'],
        components: { SomeThirdPartyIndicator },
    })
    export default class LoadedListing extends Vue {
        @Prop() readonly loadStatus!: loadStatusEnum;
        get isLoading (): boolean {
            return this.loadStatus == loadStatusEnum.Loading
        }
    }

</script>

When integrating loading in a view or a component, I utilize it as follows:

import LoadedListing, { loadStatusEnum } from '../components/LoadedListing.vue'

export default class SomePage extends Vue {
    ...
    someStuffLoadStatus: loadStatusEnum = loadStatusEnum.Loading; // 1
    loadSomeStuff (): void {
        this.someStuffLoadStatus = loadStatusEnum.Loading; // 2
        this.$store.dispatch('someModule/loadSomeStuff', ...) // some model updating in a callback
            .then(() => this.someStuffLoadStatus = loadStatusEnum.Loaded) // 3
            .catch(() => this.someStuffLoadStatus = loadStatusEnum.Failed) // 4
    }
    ...
}

and in template:

<LoadedListing class="some-stuff-list" :load-status="someStuffLoadStatus">
    <div class="some-stuff-list__top-panel"> ... </div>
    <VueSimplebar class="some-stuff-list__body" ...> ... </VueSimplebar>
</LoadedListing>

One downside of this method includes:

  • I have to repeat lines 1-4 for every loader
  • I need to create the someStuffLoadStatus property in the parent component and pass it as a prop, even though it's solely related to the component's loading status

It might be more suitable to directly integrate the loader into a specific component instance (using ref perhaps?), but the implementation process is unclear. Can you suggest an alternative approach for such integration?

Answer №1

When it comes to incorporating decoration in Typescript/Vue, one approach I took in a previous project was utilizing a mixin.

While this solution has not been tested, it outlines the basic concept of using a mixin to manage loading states:

// loading_mixin.js
export default {
    data() {
        return {
            loader: {
                // Various keys can be added here for different types passed to the `wrap()` function `type` parameter.
            }
        }
    },
    methods: {
        /**
         * @param {Promise} promise
         * @param {String} type
         * @returns {Promise}
         */
        wrap(promise, type) {
            let loaded = this.loader[type] ? this.loader[type].loaded : false;
            this.$set(this.loader, type, {loading: true, loaded: loaded});
            return promise.then((data) => {
                this.$set(this.loader, type, {loading: false, loaded: true});
                return data;
            }).catch((err) => {
                this.$set(this.loader, type, {loading: false, loaded: false});
                throw err;
            });
        },
    }
}

Implementation in (YourComponent.vue):

<template>
    <div>
        <loading-component :loader="loader.load_data" />
    </div>
</template>
<script>
    import loadingMixin from '...';
    export default {
        mixins: [loadingMixin],
        methods: {
            load() {
                this.wrap(this.loadMyData(1, 2), 'load_data').then((data) => {
                    // Handle success.
                }).catch((err) => {
                    // Handle error.
                })
            },
            loadMyData(a, b) {
                return Promise.resolve(a + b);
            }
        }
}
</script>

These concepts may inspire your approach.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide to creating an Event using Composition API in Vue3

I am currently implementing this feature within a vue3 component: <template> <div class="hamburger-toggle" @click="toggle" :class="{ nav__open: isActive }"> </template> <script> export default { ...

Issue with Vue/Laravel 5.3: Component template is not displaying on the view

Deciding to incorporate a Vue component into my view for the first time has presented some challenges. I've created a file called assets/js/components/ImageUpload.vue with the following content: <template> <div> <div v-if="!image"> ...

Definition of Redux store state object

Recently, I started using Typescript in a React/Redux project, and I am facing some confusion regarding how type definitions should be incorporated into the application state. My goal is to make a specific piece of state accessible to a container component ...

Fixing 404 Errors in Angular 2 Due to Component Relative Paths in SystemJS-Builder

I recently posted this on https://github.com/systemjs/builder/issues/611 My goal is to bundle my Angular 2 rc 1 application using systemjs-builder 0.15.16's buildStatic method. In my Angular component, there is a view and one or more external stylesh ...

What is the method for sending a CSV file as Form Data through a REST API?

I am currently struggling with encoding my uploaded CSV file to Form Data. My approach is to pass the actual file to be processed on the backend using the post method of my API. However, I keep encountering an error message saying "TypeError: Failed to con ...

Ant.design is unable to recognize a custom input component within a Form.Item in React

My issue lies in the fact that the antd form is unable to recognize my custom input as a standard antd input. Below is an excerpt of the form code (AddProduct): <Form.Item className="m-t-10" name="price" rules={[ { requir ...

What could be causing TypeScript to fetch the incorrect type definitions?

Every time I attempt to execute typescript in my project, I encounter the following issues: # ./node_modules/typescript/bin/tsc --project tsconfig.json node_modules/@types/webpack/index.d.ts:32:3 - error TS2305: Module '"../../tapable/tapable&qu ...

Vue.js encountering an issue of receiving null for the JSON data upon the initial loading phase

Currently, I am expanding my knowledge on vue.js and experimenting with calling a json file to parse the data. Although everything seems to be functioning as intended, whenever I refresh the page, there is a momentary blank screen before the data loads. In ...

Exploring the optimal procedures to asynchronously request an external API in Node.js using TypeScript

When handling a POST API request in a Node.js application built using TypeScript, it's necessary to make a call to an external API. This external API operates independently and must run in the background without impacting the response time. How can t ...

Vue.js - Pagination made easy

I am currently working on a pagination component and have encountered an issue. When users dynamically add or remove items, such as through an ajax call, I need to ensure that the correct active or disabled classes are applied to the pagination links. Fo ...

The best way to avoid routing before certain async data in the Vuex store has finished loading

I am facing a challenge in my application where I require certain data to be loaded into the VueX store before routing can commence, such as user sessions. An example scenario that showcases a race condition is as follows: // Defined routes { name: &ap ...

Leveraging Vue.js to iterate through elements using v-for and incrementing by 1 with each iteration directly

My goal is to iterate through questions.questions, gradually adding on each time like usual. However, it seems that I need to do this inline because I want to utilize the number generated to update item as the key in the second loop. <div v-for=" ...

Discrepancies in output between grunt-ts and tsc

Currently, I have set up a tsconfig.json file in combination with grunt-ts for the following grunt task: ts: { default: { tsconfig: true } Here is the content of the tsconfig.json file: { "compilerOptions": { "target": "es5", "module ...

Executing NestJS code after applying a pipe but before reaching the method handler

Is it possible to insert additional code after all the pipes have transformed but before the method handler is called? https://i.sstatic.net/IjQvv.png ...

Is it possible to manipulate an Angular #variableName in order to retrieve an ElementRef for an HTML element?

Suppose I have a scenario where I create a button like this: <button #myButton>My Button</button> ...and then use ViewChild in the following way: @ViewChild('myButton', { static: true }) createButton: ElementRef; In this case, creat ...

Using TypeScript and webpack, include the access_token in the http header when making requests with axios

I need to include an access_token in the header of axios, following this example: https://github.com/axios/axios#global-axios-defaults Currently, I am fetching the access_token using razor syntax, which is only accessible in CSHTML files. https://github ...

How come the hasOwnProperty function does not remove objects of type {}?

I am working with a complex type called ReactNode from the version @types/react 16.9.17 and TypeScript v3.7.4. import React, { ReactNode } from 'react'; My goal is to reduce this type to a new type that includes the property children. To achie ...

There is no assigned value in scope for the shorthand property. You must either declare one or provide an initializer

I'm just starting out with TypeScript. Encountering the error 'No value exists in scope for the shorthand property 'firstName'. Either declare one or provide an initializer.' while using Prisma with Next.js to create a new user in ...

Having trouble with JavaScript's Date.getUTCMilliSeconds() function?

I have a straightforward question for you. Take a look at this Angular App and try to create a new date, then print the number of UTC milliseconds of that date in the console. Can you figure out why it is returning zero? ...

Is it necessary to disrupt the promise chain in order to pass arguments through?

As a newcomer to nodejs and promises, I am facing a challenge in passing arguments into a callback function within my promise chain. The scenario is as follows: var first = function(something) { /* do something */ return something.toString(); } var second ...