9

I am trying to use a Vue.js plugin inside of a Vuex Store module.

In a component, I am able to call it like this: this.$plugin(). However, in a module, this is not set. I thought Vue.$plugin() would work since I initialize the plugin with Vue.use(plugin) and Vue being a global variable, but it doesn't.

How do I reference the plugin from a module?

5
  • Is it your plugin? Do you have the code? Commented Nov 22, 2017 at 16:53
  • Here is the plugin: github.com/euvl/vue-notification Trying to use this.$notify(). But this should apply to all plugins with instance methods. Commented Nov 22, 2017 at 16:54
  • Using this is definitely not going to work, Vuex is not an instance of Vue. Looking over the plugin it doesn't look like it gives you an easy way to do what you want. Commented Nov 22, 2017 at 16:59
  • 2
    Here's a hacky way you might do this. But I think you would probably want to create a notifications array in Vuex state, and populate it when a notification is necessary, then in Vue watch the notifications queue and pop/display them as needed. Commented Nov 22, 2017 at 17:54
  • 1
    Thats pretty much how I ended up doing. window._app = new Vue({}); and _app.$notify({}); Thanks for the help though! Commented Nov 22, 2017 at 18:01

4 Answers 4

3

The cleanest way I found is to import Vue in the store/module and then use the plugin via the Vue prototype.

import Vue from 'vue';

// .. in some logic
Vue.prototype.$dialog.alert('Something went wrong');
Sign up to request clarification or add additional context in comments.

2 Comments

This is working, thanks. I was just wondering: don't we create a sort of "double import": vue imports the module and the module imports vue?
@massimoi, I don't believe so. Circular imports would cause many issues, but it is common in Vue to import it in order to register plugins or use it's extended features.
2

This question was answered by Bert in the example provided here: https://codesandbox.io/s/jp4xmzl0xy

    import Vue from 'vue'
    import App from './App'
    import Notifications from 'vue-notification'
    import Vuex from "vuex"
    Vue.use(Notifications)
    Vue.use(Vuex)
    
    let notifier = new Vue()
    
    
    const store = new Vuex.Store({
      state:{},
      actions:{
        notify(context, payload){
          notifier.$notify(payload)
        }
      }
    })
    
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      store,
      template: '<App/>',
      components: { App }
    })

Comments

1

Pass in the vue instance as an argument

Another option is to pass the vue instance as an argument for your action.

// Vue component
{
  methods: {
    const vm = this
    this.$store.dispatch('someaction', { vm })
  }
}

// Store action
{
  someaction (context, { vm }) {
    vm.$dialog.alert('Something went wrong')
  }
}

3 Comments

This seems like the best way to go. Are there caveats to this method like building for production or anything?
@rgin There is no caveat besides the fact that you are passing in to vuex an instance of vue which is not ideal since it makes your code harder to maintain. Building this for production will work.
Thanks. Yeah, ended up having to refactor the code because of this.
0

There's a couple of other ways I've found. Honestly not sure which is the best though. I really don't like importing Vue and calling prototype methods. Seems like a complete antipattern and particularly difficult when it comes to testing using localVue as the actions have been coupled to global Vue.

  1. I'm pretty sure you're not supposed to do this but you can access the vue instance of the store from within an action using this._vm.$notify

  2. You can create a store plugin:

const notifyStore = (store) => {
  store.$notify = store._vm.$notify
}
  1. Create notify as a standalone module
import Vue from 'vue'

let notifier = new Vue()

export default notifier
  1. A combination of the two
import notifier from './notifier'

const notifyStorePlugin = (store) => {
  store.$notify = notifier.$notify
}

I'm not saying this is the definitive answer on this. I'm also very open to feedback and other suggestions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.