Complex Loader and Progress Management for Vue/Vuex and Nuxt Applications

Overview

Multiple Process Loader Management for Vue and (optionally) Vuex.

Read the Medium post "Managing Complex Waiting Experiences on Web UIs".

npm version


vue-wait

Play with demo above.

vue-wait helps to manage multiple loading states on the page without any conflict. It's based on a very simple idea that manages an array (or Vuex store optionally) with multiple loading states. The built-in loader component listens its registered loader and immediately become loading state.

Quick Start

If you are a try and learn developer, you can start trying the vue-wait now using codesandbox.io.

Edit VueWait Sandbox

1. Install:

yarn add vue-wait

2. Require:

import VueWait from 'vue-wait'

Vue.use(VueWait)

new Vue({
  // your vue config
  wait: new VueWait(),
})

3. Use in Your Components

<template>
  <v-wait for="my list is to load">
    <template slot="waiting">
      <div>
        <img src="loading.gif" />
        Loading the list...
      </div>
    </template>
    <ul>
      <li v-for="item in myList">{{ item }}</li>
    </ul>
  </v-wait>
</template>

<script>
  export default {
    data() {
      return {
        myList: []
      }
    },
    async created() {
      // start waiting
      this.$wait.start('my list is to load');

      this.myList = await fetch('/my-list-url');

      // stop waiting
      this.$wait.end('my list is to load');
    },
  };
</script>

vue-wait has more abilities to make the management easier, please read the complete documentation.

▶️ Detailed Start

📦 Requirements

🚀 Power Supplies

  • Vuex, optionally (v2.0.0+)

🔧 Installation

via CLI:

$ yarn add vue-wait
# or if you using npm
$ npm install vue-wait

via Vue UI:

📖 Usage

import VueWait from 'vue-wait'

Vue.use(VueWait) // add VueWait as Vue plugin

Then you should register wait property (VueWait instance) to the Vue instance:

new Vue({
  el: '#app',
  store,
  wait: new VueWait({
    // Defaults values are following:
    useVuex: false,              // Uses Vuex to manage wait state
    vuexModuleName: 'wait',      // Vuex module name

    registerComponent: true,     // Registers `v-wait` component
    componentName: 'v-wait',     // <v-wait> component name, you can set `my-loader` etc.

    registerDirective: true,     // Registers `v-wait` directive
    directiveName: 'wait',       // <span v-wait /> directive name, you can set `my-loader` etc.

  }),
});

♻️ Usage with Vuex

Simply set useVuex parameter to true and optionally override vuexModuleName

import VueWait from 'vue-wait'

Vue.use(Vuex)
Vue.use(VueWait) // add VueWait as Vue plugin

Then you should register VueWait module:

new Vue({
  el: '#app',
  store,
  wait: new VueWait({
    useVuex: true, // You must pass this option `true` to use Vuex
    vuexModuleName: 'vuex-example-module' // It's optional, `wait` by default.
  }),
});

Now VueWait will use Vuex store for data management which can be traced in Vue DevTools > Vuex

♻️ Usage with Nuxt.js

Add vue-wait/nuxt to modules section of nuxt.config.js

{
  modules: [
    // Simple usage
    'vue-wait/nuxt'

    // Optionally passing options in module configuration
    ['vue-wait/nuxt', { useVuex: true }]
  ],

  // Optionally passing options in module top level configuration
  wait: { useVuex: true }
}

🔁 VueWait Options

You can use this options for customize VueWait behavior.

Option Name Type Default Description
accessorName String "$wait" You can change this value to rename the accessor. E.g. if you rename this to $w, your VueWait methods will be accessible by $w.waits(..) etc.
useVuex Boolean false Use this value for enabling integration with Vuex store. When this value is true VueWait will store data in Vuex store and all changes to this data will be made by dispatching actions to store
vuexModuleName String "wait" Name for Vuex store if useVuex set to true, otherwise not used.
registerComponent Boolean true Registers v-wait component.
componentName String "v-wait" Changes v-wait component name.
registerDirective Boolean true Registers v-wait directive.
directiveName String "v-wait" Changes v-wait directive name.

🌈 Global Template Helpers

vue-wait provides some helpers to you to use in your templates. All features can be obtained from $wait property in Vue components.

.any

Returns boolean value if any loader exists in page.

<template>
  <progress-bar v-if="$wait.any">Please wait...</progress-bar>
</template>

.is(loader String | Matcher) or .waiting(loader String | Matcher)

Returns boolean value if given loader exists in page.

<template>
  <progress-bar v-if="$wait.is('creating user')">Creating User...</progress-bar>
</template>

You can use waiting alias instead of is.

<template>
  <div v-if="$wait.waiting('fetching users')">
    Fetching users...
  </div>
</template>

Also you can use matcher to make it more flexible:

Please see matcher library to see how to use matchers.

<template>
  <progress-bar v-if="$wait.is('creating.*')">Creating something...</progress-bar>
</template>

.is(loaders Array<String | Matcher>) or .waiting(loaders Array<String | Matcher>)

Returns boolean value if some of given loaders exists in page.

<template>
  <progress-bar v-if="$wait.is(['creating user', 'page loading'])">Creating User...</progress-bar>
</template>

.start(loader String)

Starts the given loader.

<template>
  <button @click="$wait.start('creating user')">Create User</button>
</template>

.end(loader String)

Stops the given loader.

<template>
  <button @click="$wait.end('creating user')">Cancel</button>
</template>

.progress(loader String, current [, total = 100])

Sets the progress of the given loader.

<template>
  <progress min="0" max="100" :value="$wait.percent('downloading')" />
  <button @click="$wait.progress('downloading', 10)">Set progress to 10</button>
  <button @click="$wait.progress('downloading', 50)">Set progress to 50</button>
  <button @click="$wait.progress('downloading', 50, 200)">Set progress to 50 of 200 (25%)</button>
</template>
Completing the Progress

To complete the progress, current value should be set bigger than 100. If you total is given, current must be bigger than total.

<button @click="$wait.progress('downloading', 101)">Set as downloaded (101 of 100)</button>

or

<button @click="$wait.progress('downloading', 5, 6)">Set as downloaded (6 of 5)</button>

.percent(loader String)

Returns the percentage of the given loader.

<template>
  <progress min="0" max="100" :value="$wait.percent('downloading')" />
</template>

🏹 Directives

You can use directives to make your template cleaner.

v-wait:visible='"loader name"'

Shows if the given loader is loading.

<template>
  <progress-bar v-wait:visible='"creating user"'>Creating User...</progress-bar>
</template>

v-wait:hidden='"loader name"' or v-wait:visible.not='"loader name"'

Hides if the given loader is loading.

<template>
  <main v-wait:hidden='"creating *"'>Some Content</main>
</template>

v-wait:disabled='"loader name"'

Sets disabled="disabled" attribute to element if the given loader is loading.

<template>
  <input v-wait:disabled="'*'" placeholder="Username" />
  <input v-wait:disabled="'*'" placeholder="Password" />
</template>

v-wait:enabled='"loader name"' or v-wait:disabled.not='"loader name"'

Removes disabled="disabled" attribute to element if the given loader is loading.

<template>
  <button v-wait:enabled='"creating user"'>Abort Request</button>
</template>

v-wait:click.start='"loader name"'

Starts given loader on click.

<template>
  <button v-wait:click.start='"create user"'>Start loader</button>
</template>

v-wait:click.end='"loader name"'

Ends given loader on click.

<template>
  <button v-wait:click.end='"create user"'>End loader</button>
</template>

v-wait:toggle='"loader name"'

Toggles given loader on click.

<template>
  <button v-wait:toggle='"flip flop"'>Toggles the loader</button>
</template>

v-wait:click.progress='["loader name", 80]'

Sets the progress of given loader on click.

<template>
  <button v-wait:click.progress='["downloading", 80]'>Set the "downloading" loader to 80</button>
</template>

🔌 Loading Action and Getter Mappers

vue-wait provides mapWaitingActions and mapWaitingGetters mapper to be used with your Vuex stores.

Let's assume you have a store and async actions called createUser and updateUser. It will call the methods you map and will start loaders while action is resolved.

import { mapWaitingActions, mapWaitingGetters } from 'vue-wait'

// ...
  methods: {
    ...mapWaitingActions('users', {
      getUsers: 'loading users',
      createUser: 'creating user',
      updateUser: 'updating user',
    }),
  },
  computed: {
    ...mapWaitingGetters({
      somethingWithUsers: [
        'loading users',
        'creating user',
        'updating user',
      ],
      deletingUser: 'deleting user',
    }),
  }
// ...

You can also map action to custom method and customize loader name like in example below:

import { mapWaitingActions, mapWaitingGetters } from 'vue-wait'

// ...
  methods: {
    ...mapWaitingActions('users', {
      getUsers: { action: 'getUsers', loader: 'loading users' },
      createUser: { action: 'createUser', loader: 'creating user'},
      createSuperUser: { action: 'createUser', loader: 'creating super user' },
    }),
  },
// ...

There is also possibility to use array as a second argument to mapWaitingActions:

// ...
  methods: {
    ...mapWaitingActions('users', [
      'getUsers',
      { method: 'createUser', action: 'createUser', loader: 'creating user'},
      { method: 'createSuperUser', action: 'createUser', loader: 'creating super user' },
    ]),
  },
// ...

☢️ Advanced Getters and Actions Usage

The Vuex module name is wait by default. If you've changed on config, you should get it by rootGetters['<vuex module name>/is'] or rootGetters['<vuex module name>/any'].

You can access vue-wait's Vuex getters using rootGetters in Vuex.

getters: {
  cartOperationInProgress(state, getters, rootState, rootGetters) {
    return rootGetters['wait/is']('cart.*');
  }
},

And you can start and end loaders using wait actions. You must pass root: true option to the dispatch method.

actions: {
  async addItemToCart({ dispatch }, item) {
    dispatch('wait/start', 'cart.addItem', { root: true });
    await CartService.addItem(item);
    dispatch('wait/end', 'cart.addItem', { root: true });
  }
},

waitFor(loader String, func Function [,forceSync = false])

Decorator that wraps function, will trigger a loading and will end loader after the original function (func argument) is finished.

By default waitFor return async function, if you want to wrap default sync function pass true in last argument

Example using with async function

import { waitFor } from 'vue-wait';

...
methods: {
  fetchDataFromApi: waitFor('fetch data', async function () {
    function sleep(ms) {
      return new Promise(resolve => setTimeout(resolve, ms));
    }
    // do work here
    await sleep(3000);
    // simulate some api call
    this.fetchResponse = Math.random()
  })
}
...

See also examples/wrap-example

💧 Using v-wait Component

If you disable registerComponent option then import and add v-wait into components

import vLoading from 'vue-wait/src/components/v-wait.vue'
components: {
  'v-wait': vLoading
}

In template, you should wrap your content with v-wait component to show loading on it.

<v-wait for='fetching data'>
  <template slot='waiting'>
    This will be shown when "fetching data" loader starts.
  </template>

  This will be shown when "fetching data" loader ends.
</v-wait>

Better example for a button with loading state:

<button :disabled='$wait.is("creating user")'>
  <v-wait for='creating user'>
    <template slot='waiting'>Creating User...</template>
    Create User
  </v-wait>
</button>

🔁 Transitions

You can use transitions with v-wait component.

Just pass <transition> props and listeners to the v-wait with transition prop.

<v-wait for="users"
  transition="fade"
  mode="out-in"
  :duration="1000"
  enter-active-class="enter-active"
  @leave='someAwesomeFinish()'
  >
  <template slot="waiting">
    <p>Loading...</p>
  </template>
  My content
</v-wait>

⚡️ Making Reusable Loader Components

With reusable loader components, you will be able to use custom loader components as example below. This will allow you to create better user loading experience.

In this example above, the tab gets data from back-end, and the table loads data from back-end at the same time. With vue-wait, you will be able to manage these two seperated loading processes easily:

<template lang='pug'>
  <div>
    <v-wait for="fetching tabs">
      <template slot="waiting">
        <b-tabs>
          <template slot="tabs">
            <b-nav-item active="active" disabled>
              <v-icon name="circle-o-notch" spin="spin" />
            </b-nav-item>
          </template>
        </b-tabs>
      </template>
      <b-tabs>
        <template slot="tabs">
          <b-nav-item v-for="tab in tabs">{{ tab.name }}</b-nav-item>
        </template>
      </b-tabs>
    </v-wait>
    <v-wait for="fetching data">
      <table-gradient-spinner slot="waiting" />
      <table>
        <tr v-for="row in data">
          <!-- ...-->
        </tr>
      </table>
    </v-wait>
  </div>
</template>

You may want to design your own reusable loader for your project. You better create a wrapper component called my-waiter:

<!-- MySpinner.vue -->
<i18n>
  tr:
    loading: Yükleniyor...
  en:
    loading: Loading...
</i18n>

<template>
  <div class="loading-spinner">
    <v-icon name="refresh" spin="spin" />
    <span>{{ $t('loading') }}</span>
  </div>
</template>

<style scoped lang="scss">
  .loading-spinner {
    opacity: 0.5;
    margin: 50px auto;
    text-align: center;
    .fa-icon {
      vertical-align: middle;
      margin-right: 10px;
    }
  }
</style>

Now you can use your spinner everywhere using slot='waiting' attribute:

<template lang="pug">
  <v-wait for="fetching data">
    <my-waiter slot="waiting" />
    <div>
      <p>My main content after fetching data...</p>
    </div>
  </v-wait>
</template>

📦 Using with external spinner libraries

You can use vue-wait with another spinner libraries like epic-spinners or other libraries. You just need to add slot="waiting" to the component and Vue handles rest of the work.

First register the component,

import { OrbitSpinner } from 'epic-spinners';
Vue.component('orbit-spinner', OrbitSpinner);

Then use it in your as a v-wait's waiting slot.

<v-wait for='something to load'>
  <orbit-spinner
    slot='waiting'
    :animation-duration="1500"
    :size="64"
    :color="'#ff1d5e'"
  />
</v-wait>

... and done!

For other libraries you can use, please see Loaders section of vuejs/awesome-vue.

🚌 Run example

Use npm run dev-vuex, npm run dev-vue or npm run dev-wrap commands. for running examples locally.

Testing components

You can test components using vue-wait but it requires configuration. Let's take a basic component for instance:

<v-wait for="loading">
   <Spinner slot="waiting" />
   <ul class="suggestions">
      <li v-for="suggestion in suggestions">{{ suggestion.Name }}</li>
   </ul>
</v-wait>
const localVue = createLocalVue();
localVue.use(Vuex); // optionally when you use Vuex integration

it('uses vue-wait component', () => {
    const wrapper = shallowMount(Suggestions, { localVue });
    expect(wrapper.find('.suggestions').exists()).toBe(true);
});

vue-test-utils will replace v-wait component with an empty div, making it difficult to test correctly.

First, make your local Vue instance use vue-wait,

const localVue = createLocalVue();
localVue.use(Vuex); // optionally when you use Vuex integration
localVue.use(VueWait);

Then inject the wait property using VueWait constructor,

it('uses vue-wait component', () => {
    const wrapper = shallowMount(SuggestedAddresses, {
      localVue,
      wait: new VueWait()
    });
    expect(wrapper.find('.suggestions').exists()).toBe(true); // it works!
});

🎯 Contributors

  • Fatih Kadir Akın, (creator)
  • Igor, (maintainer, made Vuex-free)

🔗 Other Implementations

Since vue-wait based on a very simple idea, it can be implemented on other frameworks.

  • react-wait: Multiple Process Loader Management for React.
  • dom-wait: Multiple Process Loader Management for vanilla JavaScript.

🔑 License

MIT © Fatih Kadir Akın

Issues
  • Renaming the repo

    Renaming the repo

    Since vuex-loading is not really Vuex related now, we need a new name. vue-loading is registered.

    Maybe we can find a fancier (hipster) name. Should we use vue- prefix?

    v2.0.0 
    opened by f 18
  • Big update of the whole project to be progress management for Vue

    Big update of the whole project to be progress management for Vue

    I want to add full set of features for tracking progress information (with backward compatibility) just by extending methods with optional parameters about progress.

    Because this feature will transform this library from Complex Loader Management for Vue/Vuex Applications to Complex Progress Management for Vue/Vuex Applications, propose to rename this project to Vue-progress and change description to Complex Progress Management for Vue/Vuex Applications then we can rename this.$loading to this.$progress which is much better in my opinion.

    This repo then will redirect to new repo.

    This is not necessary but will reflect much better the project purpose

    opened by sky-code 12
  • add wrapLoading helper function, fix examples, fix logging format, rename spinner to loading

    add wrapLoading helper function, fix examples, fix logging format, rename spinner to loading

    wrapLoading helper function for easy integration of vuex-loading in vue component methods

    rename v-loading slot spinner to loading - much more clear what this slot mean

    opened by sky-code 11
  • return promise in startLoading method

    return promise in startLoading method

    i have this in my acction

    export async function loadCampaign ({commit, dispatch}, {campaign, subscription}) {
      const url = route('api.campaigns.show', {campaign, subscription});
    
      commit(types.CAMPAIGN_REQUEST);
    
      try {
        const response = await startLoading(dispatch, 'load campaign', () => {
          return fetch(`${url}?include=tags`, {credentials: 'same-origin'})
            .then(response => response.json());
        });
    
        commit(
          types.CAMPAIGN_SUCCESS,
          normalize(response, schema.campaign)
        );
      } catch (err) {
        commit(types.CAMPAIGN_FAILURE, err);
      }
    }
    

    and in my view

    <div v-if="!$isLoading('load campaign')">
         <h1>{{campaign.name}}</h1>
    </div>
    

    I have an error because the loading state is updated before my update and campaign has not been set.

    opened by hosmelq 6
  • 1.0.0

    1.0.0

    v1.0.0

    • A complete rewrite, more extensible.
    • Readable and better code.
    • Update to Webpack 4
    • Remove built-in loaders. Maybe we can create another repository including custom spinners.
    • Remove width and height props.
    • Strict props.
    • isLoading supports matcher now.
    • Rename registerComponents to registerComponent
    • Added accessorName option to change $vueLoading key.
    • Removed createActionHelpers, use mapLoadingActions or wrapLoading instead.
    opened by f 6
  • vuex-loading is undefined

    vuex-loading is undefined

    The new version 0.2.5 seems to be broken.

    import VueLoading from 'vuex-loading'
    console.log(VueLoading) // output undefined
    
    opened by lbineau 6
  • Add typescript declaration file

    Add typescript declaration file

    https://www.typescriptlang.org/docs/handbook/declaration-files/templates/module-d-ts.html http://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html

    opened by Koc 6
  • Different or customizable $loading property

    Different or customizable $loading property

    I find this library extremely useful, but the used property name is causing problems for me.

    For example I'm using it along with element-ui, which also defined a this.$loading field resulting in errors.

    In VueJS documentation, there is the recommendation of giving such field unique names: https://vuejs.org/v2/style-guide/#Private-property-names-essential

    It would be great if the exposed field could be defined in the constructor options, or renamed entirely to something else like $vuexLoading

    opened by cioraneanu 6
  • TypeError: this.$loading.init is not a function

    TypeError: this.$loading.init is not a function

    Here's my question: TypeError: this.$loading.init is not a function

    use: "vue": "^2.5.9", "vuex": "^3.0.1", "vuex-loading": "^0.2.6"

    opened by 495640129 6
  • make vuex optional

    make vuex optional

    Hi there, your loader is best of this https://github.com/vuejs/awesome-vue#loader by api and features but require vuex. Can you make vuex optional for people who use it, and provide all features by plugin itself without vuex store? I can help with that if you want.

    opened by sky-code 5
  • Bump dns-packet from 1.3.1 to 1.3.4

    Bump dns-packet from 1.3.1 to 1.3.4

    Bumps dns-packet from 1.3.1 to 1.3.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump hosted-git-info from 2.7.1 to 2.8.9

    Bump hosted-git-info from 2.7.1 to 2.8.9

    Bumps hosted-git-info from 2.7.1 to 2.8.9.

    Changelog

    Sourced from hosted-git-info's changelog.

    2.8.9 (2021-04-07)

    Bug Fixes

    2.8.8 (2020-02-29)

    Bug Fixes

    • #61 & #65 addressing issues w/ url.URL implmentation which regressed node 6 support (5038b18), closes #66

    2.8.7 (2020-02-26)

    Bug Fixes

    • Do not attempt to use url.URL when unavailable (2d0bb66), closes #61 #62
    • Do not pass scp-style URLs to the WhatWG url.URL (f2cdfcf), closes #60

    2.8.6 (2020-02-25)

    2.8.5 (2019-10-07)

    Bug Fixes

    • updated pathmatch for gitlab (e8325b5), closes #51
    • updated pathmatch for gitlab (ffe056f)

    2.8.4 (2019-08-12)

    ... (truncated)

    Commits
    • 8d4b369 chore(release): 2.8.9
    • 29adfe5 fix: backport regex fix from #76
    • afeaefd chore(release): 2.8.8
    • 5038b18 fix: #61 & #65 addressing issues w/ url.URL implmentation which regressed nod...
    • 7440afa chore(release): 2.8.7
    • 2d0bb66 fix: Do not attempt to use url.URL when unavailable
    • f2cdfcf fix: Do not pass scp-style URLs to the WhatWG url.URL
    • e1b83df chore(release): 2.8.6
    • ff259a6 Ensure passwords in hosted Git URLs are correctly escaped
    • 624fd6f chore(release): 2.8.5
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by nlf, a new releaser for hosted-git-info since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump lodash from 4.17.15 to 4.17.21

    Bump lodash from 4.17.15 to 4.17.21

    Bumps lodash from 4.17.15 to 4.17.21.

    Commits
    • f299b52 Bump to v4.17.21
    • c4847eb Improve performance of toNumber, trim and trimEnd on large input strings
    • 3469357 Prevent command injection through _.template's variable option
    • ded9bc6 Bump to v4.17.20.
    • 63150ef Documentation fixes.
    • 00f0f62 test.js: Remove trailing comma.
    • 846e434 Temporarily use a custom fork of lodash-cli.
    • 5d046f3 Re-enable Travis tests on 4.17 branch.
    • aa816b3 Remove /npm-package.
    • d7fbc52 Bump to v4.17.19
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by bnjmnt4n, a new releaser for lodash since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump url-parse from 1.4.7 to 1.5.1

    Bump url-parse from 1.4.7 to 1.5.1

    Bumps url-parse from 1.4.7 to 1.5.1.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump elliptic from 6.4.1 to 6.5.4

    Bump elliptic from 6.4.1 to 6.5.4

    Bumps elliptic from 6.4.1 to 6.5.4.

    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Vue.js 3 support

    Vue.js 3 support

    Provide Vuejs v3 support

    opened by ducmerida 3
  • Bump ini from 1.3.5 to 1.3.7

    Bump ini from 1.3.5 to 1.3.7

    Bumps ini from 1.3.5 to 1.3.7.

    Commits
    • c74c8af 1.3.7
    • 024b8b5 update deps, add linting
    • 032fbaf Use Object.create(null) to avoid default object property hazards
    • 2da9039 1.3.6
    • cfea636 better git push script, before publish instead of after
    • 56d2805 do not allow invalid hazardous string as section name
    • See full diff in compare view
    Maintainer changes

    This version was pushed to npm by isaacs, a new releaser for ini since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • Bump http-proxy from 1.17.0 to 1.18.1

    Bump http-proxy from 1.17.0 to 1.18.1

    Bumps http-proxy from 1.17.0 to 1.18.1.

    Changelog

    Sourced from http-proxy's changelog.

    v1.18.1 - 2020-05-17

    Merged

    1.18.0 - 2019-09-18

    Merged

    Commits

    • [dist] New test fixtures. 7e4a0e5
    • [dist] End of an era. a9b09cc
    • [dist] Version bump. 1.18.0 9bbe486
    • [fix] Latest versions. 59c4403
    • [fix test] Update tests. dd1d08b
    • [dist] Update dependency ws to v3 [SECURITY] b00911c
    • [dist] .gitattributes all the things. fc93520
    • [dist] Regenerate package-lock.json. 16d4f8a
    Commits
    • 9b96cd7 1.18.1
    • 335aeeb Skip sending the proxyReq event when the expect header is present (#1447)
    • dba3966 Remove node6 support, add node12 to build (#1397)
    • 9bbe486 [dist] Version bump. 1.18.0
    • 6e4bef4 Added in auto-changelog module set to keepachangelog format (#1373)
    • d056241 fix 'Modify Response' readme section to avoid unnecessary array copying (#1300)
    • 244303b Fix incorrect target name for reverse proxy example (#1135)
    • b4028ba Fix modify response middleware example (#1139)
    • 77a9815 [dist] Update dependency async to v3 (#1359)
    • c662f9e Fix path to local http-proxy in examples. (#1072)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    opened by dependabot[bot] 0
  • [Bug Report] `[vuex] unknown action type: wait/start` occurred on Vue TypeScript

    [Bug Report] `[vuex] unknown action type: wait/start` occurred on Vue TypeScript

    Step to reproduce

    Using store.dispatch('wait/start', 'app loading', { root: true }) or wait/end on router.beforeEach in Vue TypeScript project.

    However, it is working fine on Vue with CommonJS project.

    Expected Behavior

    It should be worked without any error or warning.

    Actual Behavior

    There have error for unknown action type.

    [vuex] unknown action type: wait/start
    

    Environment

    • vue: 2.6.11
    • vue-wait: 1.4.8
    • typescript: 3.8.3
    opened by runyasak 3
  • import vue.d.ts in src/types/index.d.ts

    import vue.d.ts in src/types/index.d.ts

    With the following main.ts file in a Vue app:

    import Vue from "vue";
    import VueWait from "vue-wait";
    
    import App from "./App.vue";
    import "./registerServiceWorker";
    import router from "./router";
    import store from "./store";
    
    Vue.use(VueWait);
    
    Vue.config.productionTip = false;
    
    new Vue({
      router,
      store,
      render: h => h(App),
      wait: new VueWait({
        useVuex: true,
        vuexModuleName: 'wait',
      }),
    }).$mount("#app");
    

    I was experiencing this error:

    31:3 No overload matches this call.
      Overload 1 of 3, '(options?: ThisTypedComponentOptionsWithArrayProps<Vue, object, object, object, never> | undefined): CombinedVueInstance<Vue, object, object, object, Record<...>>', gave the following error.
        Argument of type '{ router: VueRouter; store: Store<unknown>; render: (h: CreateElement) => VNode; wait: VueWait; }' is not assignable to parameter of type 'ThisTypedComponentOptionsWithArrayProps<Vue, object, object, object, never>'.
          Object literal may only specify known properties, and 'wait' does not exist in type 'ThisTypedComponentOptionsWithArrayProps<Vue, object, object, object, never>'.
      Overload 2 of 3, '(options?: ThisTypedComponentOptionsWithRecordProps<Vue, object, object, object, object> | undefined): CombinedVueInstance<Vue, object, object, object, Record<...>>', gave the following error.
        Argument of type '{ router: VueRouter; store: Store<unknown>; render: (h: CreateElement) => VNode; wait: VueWait; }' is not assignable to parameter of type 'ThisTypedComponentOptionsWithRecordProps<Vue, object, object, object, object>'.
          Object literal may only specify known properties, and 'wait' does not exist in type 'ThisTypedComponentOptionsWithRecordProps<Vue, object, object, object, object>'.
      Overload 3 of 3, '(options?: ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>> | undefined): CombinedVueInstance<...>', gave the following error.
        Argument of type '{ router: VueRouter; store: Store<unknown>; render: (h: CreateElement) => VNode; wait: VueWait; }' is not assignable to parameter of type 'ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>'.
          Object literal may only specify known properties, and 'wait' does not exist in type 'ComponentOptions<Vue, DefaultData<Vue>, DefaultMethods<Vue>, DefaultComputed, PropsDefinition<Record<string, any>>, Record<...>>'.
        29 |   store,
        30 |   render: h => h(App),
      > 31 |   wait: new VueWait({
           |   ^
        32 |     useVuex: true,
        33 |     vuexModuleName: 'wait',
        34 |   }),
    Version: typescript 3.9.5
    

    My tsconfig.json looks like:

    {
      "compilerOptions": {
        "target": "esnext",
        "module": "esnext",
        "strict": true,
        "jsx": "preserve",
        "importHelpers": true,
        "moduleResolution": "node",
        "experimentalDecorators": true,
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "allowJs": true,
        "resolveJsonModule": true,
        "sourceMap": true,
        "baseUrl": ".",
        "types": [
          "webpack-env",
          "jest"
        ],
        "paths": {
          "@/*": [
            "src/*"
          ]
        },
        "lib": [
          "esnext",
          "dom",
          "dom.iterable",
          "scripthost"
        ]
      },
      "include": [
        "src/**/*.ts",
        "src/**/*.tsx",
        "src/**/*.vue",
        "tests/**/*.ts",
        "tests/**/*.tsx"
      ],
      "exclude": [
        "node_modules"
      ]
    }
    

    By adding this import the error no longer occurs. I observed this pattern in the vuetify library https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/types/index.d.ts and believe this is the correct fix though I'm not super experienced with Typescript so an update to my tsconfig may be all that's required.

    opened by PFacheris 0
Releases(1.4.6)
  • 1.4.6(Aug 21, 2019)

    Multiple Process Loader Management for Vue and (optionally) Vuex.

    Read the Medium post "Managing Complex Waiting Experiences on Web UIs".

    npm version


    vue-wait

    Play with demo above.

    vue-wait helps to manage multiple loading states on the page without any conflict. It's based on a very simple idea that manages an array (or Vuex store optionally) with multiple loading states. The built-in loader component listens its registered loader and immediately become loading state.

    ⏩Quick Start

    If you are a try and learn developer, you can start trying the vue-wait now using codesandbox.io.

    Edit VueWait Sandbox

    1. Install:

    yarn add vue-wait
    

    2. Require:

    import VueWait from 'vue-wait'
    
    Vue.use(VueWait)
    
    new Vue({
      // your vue config
      wait: new VueWait(),
    })
    

    3. Use in Your Components

    <template>
      <v-wait for="my list is to load">
        <template slot="waiting">
          <div>
            <img src="loading.gif" />
            Loading the list...
          </div>
        </template>
        <ul>
          <li v-for="item in myList">{{ item }}</li>
        </ul>
      </v-wait>
    </template>
    
    <script>
      export default {
        data() {
          return {
            myList: []
          }
        },
        async created() {
          // start waiting
          this.$wait.start('my list is to load');
    
          this.myList = await fetch('/my-list-url');
    
          // stop waiting
          this.$wait.end('my list is to load');
        },
      };
    </script>
    

    vue-wait has more abilities to make the management easier, please read the complete documentation.

    ▶️Detailed Start

    📦 Requirements

    🚀 Power Supplies

    • Vuex, optionally (v2.0.0+)

    🔧 Installation

    via CLI:

    $ yarn add vue-wait
    # or if you using npm
    $ npm install vue-wait
    

    via Vue UI:

    📖 Usage

    import VueWait from 'vue-wait'
    
    Vue.use(VueWait) // add VueWait as Vue plugin
    

    Then you should register wait property (VueWait instance) to the Vue instance:

    new Vue({
      el: '#app',
      store,
      wait: new VueWait({
        // Defaults values are following:
        useVuex: false,              // Uses Vuex to manage wait state
        vuexModuleName: 'wait',      // Vuex module name
    
        registerComponent: true,     // Registers `v-wait` component
        componentName: 'v-wait',     // <v-wait> component name, you can set `my-loader` etc.
    
        registerDirective: true,     // Registers `v-wait` directive
        directiveName: 'wait',       // <span v-wait /> directive name, you can set `my-loader` etc.
    
      }),
    });
    

    ♻️ Usage with Vuex

    Simply set useVuex parameter to true and optionally override vuexModuleName

    import VueWait from 'vue-wait'
    
    Vue.use(Vuex)
    Vue.use(VueWait) // add VueWait as Vue plugin
    

    Then you should register VueWait module:

    new Vue({
      el: '#app',
      store,
      wait: new VueWait({
        useVuex: true, // You must pass this option `true` to use Vuex
        vuexModuleName: 'vuex-example-module' // It's optional, `wait` by default.
      }),
    });
    

    Now VueWait will use Vuex store for data management which can be traced in Vue DevTools > Vuex

    ♻️ Usage with Nuxt.js

    Add vue-wait/nuxt to modules section of nuxt.config.js

    {
      modules: [
        // Simple usage
        'vue-wait/nuxt'
    
        // Optionally passing options in module configuration
        ['vue-wait/nuxt', { useVuex: true }]
      ],
    
      // Optionally passing options in module top level configuration
      wait: { useVuex: true }
    }
    

    🔁 VueWait Options

    You can use this options for customize VueWait behavior.

    | Option Name | Type | Default | Description | | ----------- | ---- | ------- | ----------- | | accessorName | String | "$wait" | You can change this value to rename the accessor. E.g. if you rename this to $w, your VueWait methods will be accessible by $w.waits(..) etc. | | useVuex | Boolean | false | Use this value for enabling integration with Vuex store. When this value is true VueWait will store data in Vuex store and all changes to this data will be made by dispatching actions to store | | vuexModuleName | String | "wait" | Name for Vuex store if useVuex set to true, otherwise not used. | | registerComponent | Boolean | true | Registers v-wait component. | | componentName | String | "v-wait" | Changes v-wait component name. | | registerDirective | Boolean | true | Registers v-wait directive. | | directiveName | String | "v-wait" | Changes v-wait directive name. |

    🌈 Global Template Helpers

    vue-wait provides some helpers to you to use in your templates. All features can be obtained from $wait property in Vue components.

    .any

    Returns boolean value if any loader exists in page.

    <template>
      <progress-bar v-if="$wait.any">Please wait...</progress-bar>
    </template>
    

    .is(loader String | Matcher) or .waiting(loader String | Matcher)

    Returns boolean value if given loader exists in page.

    <template>
      <progress-bar v-if="$wait.is('creating user')">Creating User...</progress-bar>
    </template>
    

    You can use waiting alias instead of is.

    <template>
      <div v-if="$wait.waiting('fetching users')">
        Fetching users...
      </div>
    </template>
    

    Also you can use matcher to make it more flexible:

    Please see matcher library to see how to use matchers.

    <template>
      <progress-bar v-if="$wait.is('creating.*')">Creating something...</progress-bar>
    </template>
    

    .is(loaders Array<String | Matcher>) or .waiting(loaders Array<String | Matcher>)

    Returns boolean value if some of given loaders exists in page.

    <template>
      <progress-bar v-if="$wait.is(['creating user', 'page loading'])">Creating User...</progress-bar>
    </template>
    

    .start(loader String)

    Starts the given loader.

    <template>
      <button @click="$wait.start('creating user')">Create User</button>
    </template>
    

    .end(loader String)

    Stops the given loader.

    <template>
      <button @click="$wait.end('creating user')">Cancel</button>
    </template>
    

    .progress(loader String, current [, total = 100])

    Sets the progress of the given loader.

    <template>
      <progress min="0" max="100" :value="$wait.percent('downloading')" />
      <button @click="$wait.progress('downloading', 10)">Set progress to 10</button>
      <button @click="$wait.progress('downloading', 50)">Set progress to 50</button>
      <button @click="$wait.progress('downloading', 50, 200)">Set progress to 50 of 200 (25%)</button>
    </template>
    
    Completing the Progress

    To complete the progress, current value should be set bigger than 100. If you total is given, current must be bigger than total.

    <button @click="$wait.progress('downloading', 101)">Set as downloaded (101 of 100)</button>
    

    or

    <button @click="$wait.progress('downloading', 5, 6)">Set as downloaded (6 of 5)</button>
    

    .percent(loader String)

    Returns the percentage of the given loader.

    <template>
      <progress min="0" max="100" :value="$wait.percent('downloading')" />
    </template>
    

    🏹 Directives

    You can use directives to make your template cleaner.

    v-wait:visible='"loader name"'

    Shows if the given loader is loading.

    <template>
      <progress-bar v-wait:visible='"creating user"'>Creating User...</progress-bar>
    </template>
    

    v-wait:hidden='"loader name"' or v-wait:visible.not='"loader name"'

    Hides if the given loader is loading.

    <template>
      <main v-wait:hidden='"creating *"'>Some Content</main>
    </template>
    

    v-wait:disabled='"loader name"'

    Sets disabled="disabled" attribute to element if the given loader is loading.

    <template>
      <input v-wait:disabled="'*'" placeholder="Username" />
      <input v-wait:disabled="'*'" placeholder="Password" />
    </template>
    

    v-wait:enabled='"loader name"' or v-wait:disabled.not='"loader name"'

    Removes disabled="disabled" attribute to element if the given loader is loading.

    <template>
      <button v-wait:enabled='"creating user"'>Abort Request</button>
    </template>
    

    v-wait:click.start='"loader name"'

    Starts given loader on click.

    <template>
      <button v-wait:click.start='"create user"'>Start loader</button>
    </template>
    

    v-wait:click.end='"loader name"'

    Ends given loader on click.

    <template>
      <button v-wait:click.end='"create user"'>End loader</button>
    </template>
    

    v-wait:toggle='"loader name"'

    Toggles given loader on click.

    <template>
      <button v-wait:toggle='"flip flop"'>Toggles the loader</button>
    </template>
    

    v-wait:click.progress='["loader name", 80]'

    Sets the progress of given loader on click.

    <template>
      <button v-wait:click.progress='["downloading", 80]'>Set the "downloading" loader to 80</button>
    </template>
    

    🔌 Loading Action and Getter Mappers

    vue-wait provides mapWaitingActions and mapWaitingGetters mapper to be used with your Vuex stores.

    Let's assume you have a store and async actions called createUser and updateUser. It will call the methods you map and will start loaders while action is resolved.

    import { mapWaitingActions, mapWaitingGetters } from 'vue-wait'
    
    // ...
      methods: {
        ...mapWaitingActions('users', {
          getUsers: 'loading users',
          createUser: 'creating user',
          updateUser: 'updating user',
        }),
      },
      computed: {
        ...mapWaitingGetters({
          somethingWithUsers: [
            'loading users',
            'creating user',
            'updating user',
          ],
          deletingUser: 'deleting user',
        }),
      }
    // ...
    

    You can also map action to custom method and customize loader name like in example below:

    import { mapWaitingActions, mapWaitingGetters } from 'vue-wait'
    
    // ...
      methods: {
        ...mapWaitingActions('users', {
          getUsers: { action: 'getUsers', loader: 'loading users' },
          createUser: { action: 'createUser', loader: 'creating user'},
          createSuperUser: { action: 'createUser', loader: 'creating super user' },
        }),
      },
    // ...
    

    There is also possibility to use array as a second argument to mapWaitingActions:

    // ...
      methods: {
        ...mapWaitingActions('users', [
          'getUsers',
          { method: 'createUser', action: 'createUser', loader: 'creating user'},
          { method: 'createSuperUser', action: 'createUser', loader: 'creating super user' },
        ]),
      },
    // ...
    
    
    

    ☢️Advanced Getters and Actions Usage

    The Vuex module name is wait by default. If you've changed on config, you should get it by rootGetters['<vuex module name>/is'] or rootGetters['<vuex module name>/any'].

    You can access vue-wait's Vuex getters using rootGetters in Vuex.

    getters: {
      cartOperationInProgress(state, getters, rootState, rootGetters) {
        return rootGetters['wait/is']('cart.*');
      }
    },
    

    And you can start and end loaders using wait actions. You must pass root: true option to the dispatch method.

    actions: {
      async addItemToCart({ dispatch }, item) {
        dispatch('wait/start', 'cart.addItem', { root: true });
        await CartService.addItem(item);
        dispatch('wait/end', 'cart.addItem', { root: true });
      }
    },
    

    waitFor(loader String, func Function [,forceSync = false])

    Decorator that wraps function, will trigger a loading and will end loader after the original function (func argument) is finished.

    By default waitFor return async function, if you want to wrap default sync function pass true in last argument

    Example using with async function

    import { waitFor } from 'vue-wait';
    
    ...
    methods: {
      fetchDataFromApi: waitFor('fetch data', async function () {
        function sleep(ms) {
          return new Promise(resolve => setTimeout(resolve, ms));
        }
        // do work here
        await sleep(3000);
        // simulate some api call
        this.fetchResponse = Math.random()
      })
    }
    ...
    

    See also examples/wrap-example

    💧 Using v-wait Component

    If you disable registerComponent option then import and add v-wait into components

    import vLoading from 'vue-wait/src/components/v-wait.vue'
    components: {
      'v-wait': vLoading
    }
    

    In template, you should wrap your content with v-wait component to show loading on it.

    <v-wait for='fetching data'>
      <template slot='waiting'>
        This will be shown when "fetching data" loader starts.
      </template>
    
      This will be shown when "fetching data" loader ends.
    </v-wait>
    

    Better example for a button with loading state:

    <button :disabled='$wait.is("creating user")'>
      <v-wait for='creating user'>
        <template slot='waiting'>Creating User...</template>
        Create User
      </v-wait>
    </button>
    

    🔁 Transitions

    You can use transitions with v-wait component.

    Just pass <transition> props and listeners to the v-wait with transition prop.

    <v-wait for="users"
      transition="fade"
      mode="out-in"
      :duration="1000"
      enter-active-class="enter-active"
      @leave='someAwesomeFinish()'
      >
      <template slot="waiting">
        <p>Loading...</p>
      </template>
      My content
    </v-wait>
    

    ⚡️ Making Reusable Loader Components

    With reusable loader components, you will be able to use custom loader components as example below. This will allow you to create better user loading experience.

    In this example above, the tab gets data from back-end, and the table loads data from back-end at the same time. With vue-wait, you will be able to manage these two seperated loading processes easily:

    <template lang='pug'>
      <div>
        <v-wait for="fetching tabs">
          <template slot="waiting">
            <b-tabs>
              <template slot="tabs">
                <b-nav-item active="active" disabled>
                  <v-icon name="circle-o-notch" spin="spin" />
                </b-nav-item>
              </template>
            </b-tabs>
          </template>
          <b-tabs>
            <template slot="tabs">
              <b-nav-item v-for="tab in tabs">{{ tab.name }}</b-nav-item>
            </template>
          </b-tabs>
        </v-wait>
        <v-wait for="fetching data">
          <table-gradient-spinner slot="waiting" />
          <table>
            <tr v-for="row in data">
              <!-- ...-->
            </tr>
          </table>
        </v-wait>
      </div>
    </template>
    

    You may want to design your own reusable loader for your project. You better create a wrapper component called my-waiter:

    <!-- MySpinner.vue -->
    <i18n>
      tr:
        loading: Yükleniyor...
      en:
        loading: Loading...
    </i18n>
    
    <template>
      <div class="loading-spinner">
        <v-icon name="refresh" spin="spin" />
        <span>{{ $t('loading') }}</span>
      </div>
    </template>
    
    <style scoped lang="scss">
      .loading-spinner {
        opacity: 0.5;
        margin: 50px auto;
        text-align: center;
        .fa-icon {
          vertical-align: middle;
          margin-right: 10px;
        }
      }
    </style>
    

    Now you can use your spinner everywhere using slot='waiting' attribute:

    <template lang="pug">
      <v-wait for="fetching data">
        <my-waiter slot="waiting" />
        <div>
          <p>My main content after fetching data...</p>
        </div>
      </v-wait>
    </template>
    

    📦 Using with external spinner libraries

    You can use vue-wait with another spinner libraries like epic-spinners or other libraries. You just need to add slot="waiting" to the component and Vue handles rest of the work.

    First register the component,

    import { OrbitSpinner } from 'epic-spinners';
    Vue.component('orbit-spinner', OrbitSpinner);
    

    Then use it in your as a v-wait's waiting slot.

    <v-wait for='something to load'>
      <orbit-spinner
        slot='waiting'
        :animation-duration="1500"
        :size="64"
        :color="'#ff1d5e'"
      />
    </v-wait>
    

    ... and done!

    For other libraries you can use, please see Loaders section of vuejs/awesome-vue.

    🚌 Run example

    Use npm run dev-vuex, npm run dev-vue or npm run dev-wrap commands. for running examples locally.

    ✔ Testing components

    You can test components using vue-wait but it requires configuration. Let's take a basic component for instance:

    <v-wait for="loading">
       <Spinner slot="waiting" />
       <ul class="suggestions">
          <li v-for="suggestion in suggestions">{{ suggestion.Name }}</li>
       </ul>
    </v-wait>
    
    const localVue = createLocalVue();
    localVue.use(Vuex); // optionally when you use Vuex integration
    
    it('uses vue-wait component', () => {
        const wrapper = shallowMount(Suggestions, { localVue });
        expect(wrapper.find('.suggestions').exists()).toBe(true);
    });
    

    vue-test-utils will replace v-wait component with an empty div, making it difficult to test correctly.

    First, make your local Vue instance use vue-wait,

    const localVue = createLocalVue();
    localVue.use(Vuex); // optionally when you use Vuex integration
    localVue.use(VueWait);
    

    Then inject the wait property using VueWait constructor,

    it('uses vue-wait component', () => {
        const wrapper = shallowMount(SuggestedAddresses, {
          localVue,
          wait: new VueWait()
        });
        expect(wrapper.find('.suggestions').exists()).toBe(true); // it works!
    });
    

    🎯 Contributors

    • Fatih Kadir Akın, (creator)
    • Igor, (maintainer, made Vuex-free)

    🔗 Other Implementations

    Since vue-wait based on a very simple idea, it can be implemented on other frameworks.

    • react-wait: Multiple Process Loader Management for React.
    • dom-wait: Multiple Process Loader Management for vanilla JavaScript.

    🔑 License

    MIT © Fatih Kadir Akın

    Source code(tar.gz)
    Source code(zip)
  • v1.4.6(May 28, 2019)

  • v1.4.5(May 24, 2019)

  • v1.4.4(May 24, 2019)

  • v1.4.2(May 23, 2019)

  • v1.3.3(Dec 14, 2018)

  • v1.3.0(Jul 2, 2018)

    • New Feature: Progress management. percent(waiter), progress(waiter, current, total) methods.
    • Added v-wait:click.progress="[waiter, current, total]" directive.
    • is(waiter) now has an alias: waiting(waiter)
    • GitHub Pages example updated with progress.
    Source code(tar.gz)
    Source code(zip)
  • v1.2.2(Jun 21, 2018)

  • v1.2.0(Jun 12, 2018)

  • v1.1.4(Jun 8, 2018)

  • v1.1.0(Jun 7, 2018)

  • v1.0.4(Jun 7, 2018)

  • v1.0.0(Jun 7, 2018)

    v1.0.0

    • A complete rewrite, more extensible.
    • Readable and better code.
    • Update to Webpack 4
    • Remove built-in loaders. Maybe we can create another repository including custom spinners.
    • Remove width and height props.
    • Strict props.
    • isLoading supports matchers now creating.*, !creating etc. Please see /sindresorhus/matcher.
    • Rename registerComponents to registerComponent
    • Added accessorName option to change $vueLoading key.
    • Removed createActionHelpers, use mapLoadingActions or wrapLoading instead.
    • Added v-loading:visible, v-loading:hidden, v-loading:disabled, v-loading:enabled, v-loading:click directives.
    Source code(tar.gz)
    Source code(zip)
Owner
Fatih Kadir Akın
JavaScript developer. Ruby lover. Author.
Fatih Kadir Akın
Complex Loader and Progress Management for Vue/Vuex and Nuxt Applications

Multiple Process Loader Management for Vue and (optionally) Vuex. Read the Medium post "Managing Complex Waiting Experiences on Web UIs". Play with de

Fatih Kadir Akın 1.8k Jun 7, 2021
:panda_face: A simple,progress bar for Vue.js

svg-progress-bar A simple,progress bar for Vue.js ?? online demo | ?? simple demo | ?? Chinese Document Browser support IE Firefox Chrome Safari iOS A

sos 106 May 22, 2021
Progress bars and loading indicators for Vue.js

vue-progress-path Progress bars and loading indicators that can take any form! This library is Work In Progress. Live Demo Sponsors Gold Silver Bronze

Guillaume Chau 336 Jun 5, 2021
Radial progress bar component for Vue.js

vue-radial-progress A radial progress bar component for Vue.js. Uses SVG and javascript to animate a radial progress bar with a gradient. Live Demo Re

Wyzant 375 Jun 4, 2021
Vue + loaders.css

vue loaders loaders.css + vue < previous version NPM $ npm install -S vue-loaders CDN umd: https://unpkg.com/vue-loaders/dist/vue-loaders.umd.js esm/m

Kirill Khoroshilov 130 May 18, 2021
Pre Loader components for vue.js

Demo and playground Live demo - https://vue-preloader.netlify.app/ Playground Website. Adjust the settings using the playground options. On the bottom

Bot-Academia 13 May 13, 2021
Vue.js component for full screen loading indicator :cyclone:

Vue Loading Overlay Component Vue.js component for full screen loading indicator Demo or JSFiddle Installation # yarn yarn add vue-loading-overlay #

Ankur Kumar 835 Jun 13, 2021
Stable, Flexible and Fully Customizable Vue and Nuxt preloaders library

Important! in 2.0, nuxt module has been removed. The reason is that you don't really need it. Just use it as a vue plugin. Vue Preloaders Stable, Flex

igal leikin 37 Apr 7, 2021
Vite 2.x plugin to load SVG files as Vue components

Vite SVG loader Vite 2.x plugin to load SVG files as Vue components. <template> <MyIcon /> </template> <script setup> import MyIcon from './my-icon

Jan-Paul Kleemans 51 Jun 11, 2021
BlockUI for vue 2, similiar to jquery blockUI, can be used for loading screen.

vue-blockui BlockUI for vue 2, similiar to jquery blockUI, can be used for loading screen. Table of contents Installation Usage Demo Screens Installat

Jeff 57 Mar 28, 2021
⏳ Loading inside a container or full screen for Vue.js

vue-element-loading ⏳ Loading inside a container or full screen for Vue.js ?? Document & Demo Page Docs & Live demo Fully feature live demo ?? Install

Pongsatorn 256 Jun 7, 2021
Youtube Like Loading Bar Component for Vue.js

vue-loading-bar Loading Bar Component for Vue.Js DEMO Need Vue 2 Version? Click Here... Intro Vue Loading Bar is a Youtube like loading bar component

Naufal Rabbani 139 May 15, 2021
💫 A collection of loading spinner components for Vuejs

Vue Spinners A Vue.js port of react-spinners. ?? Installation npm install --save @saeris/vue-spinners # or yarn add @saeris/vue-spinners ?? Usage Ther

Drake Costa 269 Jun 4, 2021
Blazing fast scrolling and updating for any amount of list and hierarchical data.

Vue Virtualised Vue components developed by Vue.js 3.0 for efficiently rendering large scrollable lists and hierarchical data. vue-virtualised is able

Junxiang Chen 11 Jun 6, 2021