Example of a floating undo bar using a dynamic function in a Vuex store module

Issue Overview

  1. 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).
  2. 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/

Answer №1

Have you tried using the rollbackRemoveItem method in your store?

You might want to consider something like the following code snippet:

connect() {
  const connection = getModule(Connection, this.$store);
  connection.testAction();
  this.$store.dispatch('Connection/rollbackRemoveItem');
}

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

What is the best way to organize my NPM package with separate directories for types and functions?

I am currently working on developing a custom NPM package that will serve as a repository for sharing types and functions across my project. Let's name this project wordle. Given the emphasis on types, it is worth noting that I am using TypeScript for ...

The designated function name can be either "onButtonClick" or "onClickButton"

I am a Japanese developer working on web projects. Improving my English language skills is one of my goals. What would be the correct name for a function that indicates "when a button has been clicked"? Is it "onButtonClick"? Maybe "onClickButton"? Co ...

data in Vue not updating after setting value in session storage

I recently encountered an issue with setting values to session storage in my main.ts file after making an axios call. Despite successfully saving the data, I found that accessing it in another component resulted in 'undefined' values. It seems li ...

Convert JSON data to an array using Observable

My current task involves parsing JSON Data from an API and organizing it into separate arrays. The data is structured as follows: [ {"MONTH":9,"YEAR":2015,"SUMAMT":0}, {"MONTH":10,"YEAR":2015,"SUMAMT":11446.5}, {"MONTH":11,"YEAR":2015,"SUMAMT":5392 ...

Exploring Angular2's DOMContentLoaded Event and Lifecycle Hook

Currently, I am utilizing Angular 2 (TS) and in need of some assistance: constructor(public element:ElementRef){} ngOnInit(){ this.DOMready() } DOMready() { if (this.element) { let testPosition = this.elemen ...

Creating a custom autocomplete search using Angular's pipes and input

Trying to implement an autocomplete input feature for any field value, I decided to create a custom pipe for this purpose. One challenge I'm facing is how to connect the component displaying my JSON data with the component housing the autocomplete in ...

Establish a Vue application to run on Nginx at port 80 in Raspbian, paired with a Flask backend operating on port 8080

My setup involves Nginx running a Flask-based backend on port 8080 with the following configuration: server { listen 8080 default_server; listen [::]:8080; root /var/www/html; server_name _; location /static { alias /var/www ...

Inheritance of Generic Types in TypeScript

Could someone assist me in understanding what is incorrect with the code snippet provided here? I am still learning Typescript. interface ICalcValue { readonly IsNumber: boolean; readonly IsString: boolean; } interface ICalcValue<T> ex ...

Tips for passing a function and an object to a functional component in React

I am struggling with TypeScript and React, so please provide clear instructions. Thank you in advance for your help! My current challenge involves passing both a function and an object to a component. Let's take a look at my component called WordIte ...

Automatically shift focus to the next input when reaching the maximum length in Angular

Looking for a smoother way to focus the next input element in Angular without manually specifying which one. Here's my current HTML setup... <div class="mb-2 digit-insert d-flex align-items-center"> <div class="confirmation-group d-flex"&g ...

Discovering the worth of a variable outside of a subscription or Promise within Ionic 3

Apologies for my English. I am encountering an issue when attempting to view the results of a REST API using both subscribe and Promise methods. Within my provider, I have the following code: Provider: import { HttpClient } from '@angular/common/h ...

ESLint warning: Potentially risky assignment of an undetermined data type and hazardous invocation of an undetermined data type value

Review this test code: import { isHtmlLinkDescriptor } from '@remix-run/react/links' import invariant from 'tiny-invariant' import { links } from '~/root' it('should return a rel=stylesheet', () => { const resp ...

Enumeration in zod validation

Currently, I am using a schema in zod and have an object. const escortTypeOptions = [ { value: "Nutrition", label: "תזונה" }, { value: "Training", label: "אימונים" }, { value: "Nutrition ...

Creating a dynamic visual experience with Angular 2: How to implement multiple font colors

I have a text area which is connected to one string, with the default text color set to white. <textarea style="background-color: black;color:#fff;" [(ngModel)]="outputText"></textarea> The connected string contains multiple variables. retur ...

During the rendering process, the property "quote" was accessed, however, it is not defined on the current instance. (Vue.js)

Every time I try to retrieve data from the kanye API, I encounter this error message: Property "quote" was accessed during render but is not defined on instance. Below is the code snippet that triggered the error: <template> <div> ...

Dynamic row addition in Material Design Lite table causes format to break

Here's the HTML markup for creating a checkbox using material-design-lite: <label class="mdl-checkbox mdl-js-checkbox mdl-js-ripple-effect" for="checkbox"> <input type="checkbox" id="checkbox" class="mdl-checkbox__input" /> <span c ...

What is the best way to implement filter functionality for individual columns in an Angular material table using ngFor?

I am using ngFor to populate my column names and corresponding data in Angular. How can I implement a separate filter row for each column in an Angular Material table? This filter row should appear below the header row, which displays the different column ...

Images are not being shown by Glide JS

I have implemented the Glide JS carousel within a VueJS project to showcase multiple images, however, I am encountering an issue where only the first image is being displayed. The <img/> tag has the correct src URL for all three images, but only th ...

Set the style of the mat-select element

I'm having an issue with my select option in Angular Material. The options look fine, but when I select one, the strong tag disappears. Can anyone help me style only that part? Thank you in advance. <mat-select formControlName="projectId" ...

"In Typescript, receiving the error message "Attempting to call an expression that is not callable" can be resolved

I am in the process of creating a function that matches React's useState signature: declare function useState<S>( initialState: S | (() => S), ): [S, React.Dispatch<React.SetStateAction<S>>]; Below is an excerpt from the functi ...