vue-wait
vue-wait copied to clipboard
vuex-module-decorators Integration
Is there a way to integrate this with vuex-module-decorators? mapWaitingActions won't work here since the action ist mapped in by @Action
.
Example taken from https://blog.logrocket.com/how-to-write-a-vue-js-app-completely-in-typescript/ but with modifications to make it work:
npm install vuex-module-decorators -D
npm install vuex-class -D
// store/modules/user.ts
import { VuexModule, Module, Mutation, Action } from 'vuex-module-decorators'
import store from "@/store";
interface IUserState {
name: string
}
@Module({ store: store, namespaced: true })
export default class User extends VuexModule implements IUserState {
public name: string = ''
@Mutation
public setName(newName: string): void {
this.name = newName
}
get nameUpperCase() {
return this.name.toUpperCase();
}
@Action
public updateName(newName: string): void {
this.context.commit('setName', newName)
}
}
export default User
// store.ts
import Vue from 'vue'
import Vuex from 'vuex'
import User from '@/store/modules/user'
Vue.use(Vuex)
const store = new Vuex.Store({
modules: {
user: User
}
})
export default store
<!-- User.vue -->
<template>
<div class="details">
<div class="username">User: {{ nameUpperCase }}</div>
<input :value="name" @keyup="updateName($event.target.value)" />
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { namespace } from 'vuex-class'
const user = namespace('user')
@Component
export default class User extends Vue {
@user.State
public name!: string
@user.Getter
public nameUpperCase!: string
@user.Action
public updateName!: (newName: string) => void
}
</script>
And a variant of the similar @MutateAction
:
// store/modules/user.ts
import {
Module, Mutation, MutationAction,
VuexModule, Action,
} from 'vuex-module-decorators';
import { Veterinarian, VeterinarianControllerApi, VeterinarianSpecialisationEnum } from '@/services';
import { Getter } from 'vuex-class';
import store from '@/store';
interface IUserState {
name: string
}
@Module({ store, namespaced: true })
export default class User extends VuexModule implements IUserState {
public name: string = 'defaultValue'
get nameUpperCase() {
return this.name.toUpperCase();
}
@MutationAction({ mutate: ['name'] })
async updateName(newName: string) {
return { name: newName };
}
}
Wrapping the invocation of the Actions would be nice to trigger the wait start and end.
What I tried:
I created my own WaitingMutationAction
decorator. I just took the original one and wrapped the action with start and end:
WaitingMutationAction
export interface MutationActionParams<M> {
mutate?: (keyof Partial<M>)[]
rawError?: boolean
root?: boolean
}
-function mutationActionDecoratorFactory<T extends Object>(params: MutationActionParams<T>) {
+function waitingMutationActionDecoratorFactory<T extends Object>(params: MutationActionParams<T>) {
return function(
target: T,
key: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<Partial<T>>>
) {
const module = target.constructor as Mod<T, any>
const action: Act<typeof target, any> = async function(
context: ActionContext<typeof target, any>,
payload: Payload
) {
try {
+ this._vm.$wait.start("test");
const actionPayload = await mutactFunction.call(context, payload)
context.commit(key as string, actionPayload)
} catch (e) {
if (params.rawError) {
throw e
} else {
console.error('Could not perform action ' + key.toString())
console.error(e)
return Promise.reject(e)
}
+ } finally {
+ this._vm.$wait.end("test");
}
}
const mutation: Mut<typeof target> = function(
state: typeof target | Store<T>,
payload: Payload & { [k in keyof T]: any }
}
module.actions![key as string] = params.root ? { root: true, handler: action } : action
module.mutations![key as string] = mutation
}
}
-export function MutationAction<K, T extends K>(
+export function WaitingMutationAction<K, T extends K>(
target: { [k in keyof T]: T[k] | null },
key: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<K>>
): void
-export function MutationAction<T>(
+export function WaitingMutationAction<T>(
params: MutationActionParams<T>
): (
target: T,
key: string | symbol,
descriptor: TypedPropertyDescriptor<(...args: any[]) => Promise<T>>
) => void
*
* @param paramsOrTarget the params or the target class
* @param key the name of the function
* @param descriptor the function body
* @constructor
*/
-export function MutationAction<T, K, M extends K>(
+export function WaitingMutationAction<T, K, M extends K>(
paramsOrTarget: MutationActionParams<T> | M,
key?: string | symbol,
descriptor?: TypedPropertyDescriptor<(...args: any[]) => Promise<Partial<K>>>
):
| ((
target: T,
@MutationAction({mutate: ['incrCount']})
async getCountDelta() {
return {incrCount: 5}
}
* </pre>
*/
- return mutationActionDecoratorFactory(paramsOrTarget as MutationActionParams<T>)
+ return waitingMutationActionDecoratorFactory(paramsOrTarget as MutationActionParams<T>)
} else {
/*
* This is the case when `paramsOrTarget` is target.
* i.e. when used as -
* <pre>
@MutationAction
async getCountDelta() {
return {incrCount: 5}
}
* </pre>
*/
- mutationActionDecoratorFactory({} as MutationActionParams<K>)(
+ waitingMutationActionDecoratorFactory({} as MutationActionParams<K>)(
paramsOrTarget as K,
key!,
descriptor!
)
}
}