0
votes

Suppose I have a tree of component like this:

<widget>
  <widget-header>
    <panel-toggle></panel-toggle>
  </widget-header>
  <widget-body>
    <panel></panel>
  </widget-body>
</widget>

Now supposed I want the panel-toggle component to be able to toggle the visibility of the panel component. I could have it affect a prop passed down from widget through to each component, but that didn't seem like the best solution. I tried sending an event with this.$emit(eventName) but the event is only picked up by the immediate parent of the element emitting the event. In this case, that would be panel-toggle emitting the event and only widget-header being able to pick it up. I tried sending the event across the root element with this.$root.$emit(eventName) and picking it up with this.$root.$on(eventName), but then it is picked up by all widget components and that is no good. What I ended up doing is sending the event with this.$parent.$parent.$emit(eventName) and then picking it up from panel with this.$parent.$parent.$on(eventName). While that worked, it doesn't seem like the right way to go about this.

What would be the correct way to achieve this communication between components within the component widget only with Vue? Is the answer somehow related to the ref feature?

1
Inter component communication is typically handled via events (as you demonstrated) or with state management, i.e. Vuex. I've answered the Vuex side here - user320487
adding to what btl mentioned you could use an EventBus, - Mohd_PH
Now, I did look at that. Perhaps I don't understand, but isn't it for passing events around an application globally? In my example wouldn't the panel-toggle affect every panel in the application, which would not be the desired behavior? Could I use a Vue Event Bus to send events within a particular component, and if so, how? Thanks! - Aaron Beaudoin

1 Answers

0
votes

Since you're concerned (and with good reason) about the globalness of a global event bus, the solution is a localized event bus. Create a data item in the parent:

panelBus: new Vue()

and pass it to each of the children as a prop. Now they have a private communcation channel for just the two of them.