entio
entio

Reputation: 4253

Calling method of another router-view's component / Vue.js

I have two <router-view/>s: main and sidebar. Each of them is supplied with a component (EditorMain.vue and EditorSidebar.vue).

EditorMain has a method exportData(). I want to call this method from EditorSidebar on button click.

What is a good way of tackling it?

Is there any good practice for this? Or did i make some mistakes with the way app is set up? Did is overlooked something in documentation?

Upvotes: 3

Views: 1531

Answers (2)

Brian Lee
Brian Lee

Reputation: 18187

You could create a plugin for handling exports:

import Vue from 'vue'

ExportPlugin.install = function (Vue, options) {
  const _data = new Map()
  Object.defineProperty(Vue.prototype, '$exporter', {
      value: {
          setData: (svg) => {
              _data.set('svg', svg)
          },
          exportData: () => {
              const svg = _data.get('svg')
              // do data export...
          }
       }
  })
}

Vue.use(ExportPlugin)

Using like:

// EditorMain component
methods: {
    setData (data) {
        this.$exporter.setData(data)
    }
}

// EditorSidebar
<button @click="$exporter.exportData">Export</button>

Upvotes: 1

entio
entio

Reputation: 4253

After two more years of my adventure with Vue I feel confident enough to answer my own question. It boils down to communication between router views. I've presented two possible solutions, I'll address them separately:

Events bus

Use global events bus (but it doesn't feel right to use it together with vuex)

Well, it may not feel right and it is surely not a first thing you have to think about, but it is perfectly fine use-case for event-bus. The advantage of this solution would be that the components are coupled only by the event name.

Router-view event listeners

I could handle it in root of my app by adding event listener to router-view <router-view @exportClick="handleExportData"> and then target editor component, but it does not feel right as well as later i could need 100 listeners.

This way of solving this problem is also fine, buy it couples components together. Coupling happens in the component containing <router-view/> where all the listeners are set.

Big number of listeners could be addressed by passing an object with event: handler mapping pairs to v-on directive; like so:

<router-view v-on="listeners"/>

...

data () {
   return {
      listeners: {
         'event-one': () => console.log('Event one fired!'),
         'event-two': () => console.log('The second event works as well!')
      }
   }

Upvotes: 1

Related Questions