Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

vuex-module-decorators Integration #90

Open
No3x opened this issue Apr 11, 2020 · 0 comments
Open

vuex-module-decorators Integration #90

No3x opened this issue Apr 11, 2020 · 0 comments

Comments

@No3x
Copy link

No3x commented Apr 11, 2020

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!
     )
   }
 }
Well, it works. But it's too much code duplication and dumb.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant