Issue Overview
- Trigger the mutation or action of Vuex store module A to execute an external function. This external function can belong to another Vuex store module (e.g. B).
- A should store a reference to the external method (e.g. mutation or action from Vuex store module B) as it will be indirectly invoked at a later time.
In the example below:
- A will represent
RollbackActionFloatingPanelStoreModule
- B will represent
OtherStoreModule
- The external function will be referred to as
rollbackRemoveItem
Scenario (Use Case)
This floating undo panel allows users to revert their actions, but the undo functionality must be implemented. Since multiple types of user interactions need to be rolled back, the undo method needs to be specified each time.
https://i.stack.imgur.com/GBk2A.png
$ref
is not suitable for TypeScript-based Vue applications, so using the $ref
solution becomes necessary. I aim to offload the undo panel state and behavior entirely to a Vuex module, making the Vue component logic-free:
import { Vue, Component } from "vue-property-decorator";
import { getModule } from "vuex-module-decorators";
import template from "./RollbackActionFloatingPanel.pug";
import RollbackActionFloatingPanelStoreModule
from "@Store/modules/AssociatedWithComponents/RollbackActionFloatingPanel";
@Component({ template })
export default class RollbackActionFloatingPanel extends Vue {
private readonly relatedStoreModule: RollbackActionFloatingPanelStoreModule =
getModule(RollbackActionFloatingPanelStoreModule);
}
Component template (pug language; svg icons are encapsulated within pug mixins)
transition(name="rollback_action_floating_panel")
.RollbackActionFloatingPanel(v-show="relatedStoreModule.displayFlag")
+Checkmark__Simple__Bold--MaterialDesignIcon.RollbackActionFloatingPanel-CheckmarkIcon
.RollbackActionFloatingPanel-Text {{ relatedStoreModule.message }}
button.RollbackActionFloatingPanel-Button(@click="relatedStoreModule.onClickRollbackButton")
+Undo__Simple--MaterialDesignIcon.ButtonWithPrependedIcon-Icon
| Undo
button.RollbackActionFloatingPanel-Button.RollbackActionFloatingPanel-Button__Primary(@click="relatedStoreModule.dismiss")
+Hide__StrikethroughEye__Filled--MaterialDesignIcon.ButtonWithPrependedIcon-Icon
| Hide
The vuex store RollbackActionFloatingPanel
only requires one public method: displayAndHideALittleLater
. It could be called from other store modules or Vue components. The undo method implementation can be specified as a parameter (
displayAndHideALittleLater(payload: { message: string; onClickRollbackButton: Function; })
).
Despite being called in the template, methods onClickRollbackButton
and dismiss
cannot be restricted by TypeScript since they are not public.
import { VuexModule, Module, Mutation, Action } from "vuex-module-decorators";
import store, { StoreModuleNames } from "@Store/Store";
@Module({
name: "VUEX_MODULE:UNDO_PANEL",
store,
dynamic: true,
namespaced: true
})
export default class RollbackActionFloatingPanelStoreModule extends VuexModule {
// Vuex module contents detailed here
}
Instructions for usage with another Vuex module:
import { VuexModule, Module, Mutation, getModule } from "vuex-module-decorators";
import store, { StoreModuleNames } from "@ProjectInitializer:Store/Store";
import RollbackActionFloatingPanelStoreModule
from "@ProjectInitializer:Store/modules/AssociatedWithComponents/RollbackActionFloatingPanel";
@Module({
name: "VUEX_MODULE:OTHER"
store,
dynamic: true,
namespaced: true
})
export default class OtherStoreModule extends VuexModule {
// Contents of the OtherStoreModule explained here.
}
Error details
https://i.stack.imgur.com/fxKTF.png
Error message displayed: ERR_ACTION_ACCESS_UNDEFINED: Attempting to access this.someMutation()
or this.someGetter within an @Action?
This is permissible only in dynamic modules.
If not dynamic, utilize this.context.commit("mutationName", payload) and
this.context.getters["getterName"]
Error: Could not perform action onClickRollbackButton
This error occurs because all of my modules are dynamic, although the accuracy of the error message might be questionable. In reality, we invoke the rollbackRemoveItem
mutation through the non-decorated function _onClickRollbackButton
via the onClickRollbackButton
action. Avoiding _onClickRollbackButton
isn't straightforward since we need to retain the undo method implementation until the dismiss
mutation is executed.
Attempt with static class field
@Module({
name: "VUEX_MODULE:UNDO_PANEL",
store,
dynamic: true,
namespaced: true
})
export default class RollbackActionFloatingPanelStoreModule extends VuexModule {
// Content mentioned here for static class field attempt.
}
Same error persists.
Reproduction Case
I have created a reproduction case as a GitHub Repository which you can clone or download. To run the project, execute
npm i && npm run JavaScriptBuild
in the project directory after installing all dependencies. Once the build is complete, you can access the output at http://localhost:8081/