0

I read up on passing variables from child to parent using $emit but I can't fully figure it out yet.

In App.vue I have a <header/> component for the page header containing a button which controls the mobile navigation's visibility. On click it changes its class:

<button @click="toggleMobileNavigation" :class="isOpen ? 'is-open' : 'is-closed'">

The <header/>'s js:

export default {
  data() {
    return {
      isOpen: false,
    };
  },
  methods: {
    toggleMobileNavigation() {
      if(!this.isOpen) {
        this.isOpen = true;
      } else {
        this.isOpen = false;
      }
      this.$emit(this.isOpen)
    }
  }
}

The App.vue:

<Header />
<main id="main" tabindex="-1" class="main" :class="isOpen">

This obviously this doesn't work and I can't figure out what the right way is to catch the $emit.

Thanks for any tips!

1
  • use vuex, or make header a plugin which has its own event bus, or pass a global :state="state" prop around which has a header.isOpen prop, or add a ref to header and access through this.$refs.header, or a global event bus or traverse up from this to $root then into header component, there is a few ways Commented Dec 27, 2020 at 22:26

1 Answer 1

1

I would say you are on the right track, this child needs to emit some event to alert its parent of an important change.

But instead of doing this in your Header component:

      this.$emit(this.isOpen)

Supply an event name:

      this.$emit('opened', this.isOpen)
      // or:
      if (this.isOpen) { 
          this.$emit('opened');
      } else {
          this.$emit('closed');
      }

The way you catch this event in the parent component (App.vue) should be:

<Header @opened="handleOpenedEvent">  // will call method handleOpenedEvent
// alternatively:
<Header @opened="menuStatus = $event"> // $event contains data you supply as second argument to your this.$emit(name, ...) call

// @[eventname] is one way of doing it, v-on is the same:
<Header v-on:opened="handleEvent">
Sign up to request clarification or add additional context in comments.

11 Comments

Hey! Thanks your answer, it brought me on the right track. Somehow I also have to set emits: ["sendnavigationstatus"] in export default inside the child template. Anyways, thx al lot Joshua and have a happy new year!
Hi Anna, I wasn't aware of that (emits property) being neccessary, I've tried to look for this in the Vue docs but couldn't find it. Could you point me in the right direction? Happy new year to you too.
Thanks, learned something! I was working with Vue 2 that's why I missed it!
You have this local variable (let isOpen), which is something Vue doesn't know exists. I would add isOpen to the data function, in navigationStatus() replace the local variable isOpen with this.isOpen. That should work, at least in Vue 2 i know it will ;-). If you use Vue3 composition api with those ref types maybe look here: v3.vuejs.org/guide/composition-api-introduction.html
Another thing to note about the dynamic class names, you use it this way: :class='{someClass: isOpen}' or :class=" 'dynamic-string' + (isOpen ? 'opened' : '')"'
|

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.