VueJs 2.0 emit event from grand child to his grand parent component











up vote
36
down vote

favorite
7












It seems that Vue.js 2.0 doesn't emit events from a grand child to his grand parent component.



Vue.component('parent', {
template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
data(){
return {
action: 'No action'
}
},
methods: {
performAction() { this.action = 'actionDone' }
}
})

Vue.component('child', {
template: '<div>I am the child <grand-child></grand-child></div>'
})

Vue.component('grand-child', {
template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
methods: {
doEvent() { this.$emit('eventtriggered') }
}
})

new Vue({
el: '#app'
})


This JsFiddle solves the issue https://jsfiddle.net/y5dvkqbd/4/ , but by emtting two events:




  • One from grand child to middle component

  • Then emitting again from middle component to grand parent


Adding this middle event seems repetitive and unneccessary. Is there a way to emit directly to grand parent that I am not aware of?










share|improve this question


























    up vote
    36
    down vote

    favorite
    7












    It seems that Vue.js 2.0 doesn't emit events from a grand child to his grand parent component.



    Vue.component('parent', {
    template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
    data(){
    return {
    action: 'No action'
    }
    },
    methods: {
    performAction() { this.action = 'actionDone' }
    }
    })

    Vue.component('child', {
    template: '<div>I am the child <grand-child></grand-child></div>'
    })

    Vue.component('grand-child', {
    template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
    methods: {
    doEvent() { this.$emit('eventtriggered') }
    }
    })

    new Vue({
    el: '#app'
    })


    This JsFiddle solves the issue https://jsfiddle.net/y5dvkqbd/4/ , but by emtting two events:




    • One from grand child to middle component

    • Then emitting again from middle component to grand parent


    Adding this middle event seems repetitive and unneccessary. Is there a way to emit directly to grand parent that I am not aware of?










    share|improve this question
























      up vote
      36
      down vote

      favorite
      7









      up vote
      36
      down vote

      favorite
      7






      7





      It seems that Vue.js 2.0 doesn't emit events from a grand child to his grand parent component.



      Vue.component('parent', {
      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
      data(){
      return {
      action: 'No action'
      }
      },
      methods: {
      performAction() { this.action = 'actionDone' }
      }
      })

      Vue.component('child', {
      template: '<div>I am the child <grand-child></grand-child></div>'
      })

      Vue.component('grand-child', {
      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
      methods: {
      doEvent() { this.$emit('eventtriggered') }
      }
      })

      new Vue({
      el: '#app'
      })


      This JsFiddle solves the issue https://jsfiddle.net/y5dvkqbd/4/ , but by emtting two events:




      • One from grand child to middle component

      • Then emitting again from middle component to grand parent


      Adding this middle event seems repetitive and unneccessary. Is there a way to emit directly to grand parent that I am not aware of?










      share|improve this question













      It seems that Vue.js 2.0 doesn't emit events from a grand child to his grand parent component.



      Vue.component('parent', {
      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
      data(){
      return {
      action: 'No action'
      }
      },
      methods: {
      performAction() { this.action = 'actionDone' }
      }
      })

      Vue.component('child', {
      template: '<div>I am the child <grand-child></grand-child></div>'
      })

      Vue.component('grand-child', {
      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
      methods: {
      doEvent() { this.$emit('eventtriggered') }
      }
      })

      new Vue({
      el: '#app'
      })


      This JsFiddle solves the issue https://jsfiddle.net/y5dvkqbd/4/ , but by emtting two events:




      • One from grand child to middle component

      • Then emitting again from middle component to grand parent


      Adding this middle event seems repetitive and unneccessary. Is there a way to emit directly to grand parent that I am not aware of?







      javascript vuejs2 vue.js






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Mar 5 '17 at 23:45









      BassMHL

      1,84912341




      1,84912341
























          5 Answers
          5






          active

          oldest

          votes

















          up vote
          20
          down vote



          accepted










          The Vue community generally favors using Vuex to solve this kind of issue. Changes are made to Vuex state and the DOM representation just flows from that, eliminating the need for events in many cases.



          Barring that, re-emitting would probably be the next best choice, and lastly you might choose to use an event bus as detailed in the other highly voted answer to this question.



          The answer below is my original answer to this question and is not an approach I would take now, having more experience with Vue.





          This is a case where I might disagree with Vue's design choice and resort to DOM.



          In grand-child,



          methods: {
          doEvent() {
          try {
          this.$el.dispatchEvent(new Event("eventtriggered"));
          } catch (e) {
          // handle IE not supporting Event constructor
          var evt = document.createEvent("Event");
          evt.initEvent("eventtriggered", true, false);
          this.$el.dispatchEvent(evt);
          }
          }
          }


          and in parent,



          mounted(){
          this.$el.addEventListener("eventtriggered", () => this.performAction())
          }


          Otherwise, yes, you have to re-emit, or use a bus.



          Note: I added code in the doEvent method to handle IE; that code could be extracted in a reusable way.






          share|improve this answer























          • This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
            – BassMHL
            Mar 7 '17 at 22:39










          • @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
            – Bert
            Mar 7 '17 at 22:45




















          up vote
          16
          down vote













          Yes, you're correct events only go from child to parent. They don't go further, e.g. from child to grandparent.



          The Vue documentation (briefly) addresses this situation in the Non Parent-Child Communication section.



          The general idea is that in the grandparent component you create an empty Vue component that is passed from grandparent down to the children and grandchildren via props. The grandparent then listens for events and grandchildren emit events on that "event bus".



          Some applications use a global event bus instead of a per-component event bus. Using a global event bus means you will need to have unique event names or namespacing so events don't clash between different components.



          Here is an example of how to implement a simple global event bus.






          share|improve this answer




























            up vote
            6
            down vote













            Another solution will be:



            Uses vm.$root.$emit in grand-child, then uses vm.$root.$on at the ancestor (or anywhere you'd like).






            Vue.component('parent', {
            template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
            data(){
            return {
            action: 'No action'
            }
            },
            created: function () {
            this.$root.$on('eventtriggered1', () => {
            this.performAction()
            })
            },
            methods: {
            performAction() { this.action = 'actionDone' }
            }
            })

            Vue.component('child', {
            template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
            methods: {
            doEvent() {
            //this.$emit('eventtriggered')
            }
            }
            })

            Vue.component('grand-child', {
            template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
            methods: {
            doEvent() { this.$root.$emit('eventtriggered1') }
            }
            })

            new Vue({
            el: '#app'
            })

            <script src="https://unpkg.com/vue/dist/vue.js"></script>

            <div id="app">
            <parent></parent>
            </div>








            share|improve this answer





















            • Most elegant solution to me.
              – Ovilia
              Sep 22 at 7:27


















            up vote
            3
            down vote













            NEW ANSWER (Nov-2018 update)



            I discovered that we could actually do this by leveraging the $parent property in the grand child component:



            this.$parent.$emit("submit", {somekey: somevalue})


            Much cleaner and simpler.






            share|improve this answer





















            • Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
              – Qtax
              Dec 4 at 17:31


















            up vote
            0
            down vote













            This is the only case when I use event bus!! For passing data from deep nested child, to not directly parent, communication.




            First: Create a js file (I name it eventbus.js) with this content:




            import Vue from 'vue'    
            Vue.prototype.$event = new Vue()



            Second: In your child component emit an event:




            this.$event.$emit('event_name', 'data to pass')



            Third: In the parent listen to that event:




            this.$event.$on('event_name', (data) => {
            console.log(data)
            })


            Note: If you don't want that event anymore please unregister it:



            this.$event.$off('event_name')



            INFO: No need to read the below personal opinion




            I don't like to use vuex for grand-child to grand-parent communication (Or similar communication level).




            In vue.js for passing data from grand-parent to grand-child you can use provide/inject. But there is not something similar for the opposite thing. (grand-child to grand-parent) So I use event bus whenever I have to do that kind of communication.







            share|improve this answer





















              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42615445%2fvuejs-2-0-emit-event-from-grand-child-to-his-grand-parent-component%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              5 Answers
              5






              active

              oldest

              votes








              5 Answers
              5






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes








              up vote
              20
              down vote



              accepted










              The Vue community generally favors using Vuex to solve this kind of issue. Changes are made to Vuex state and the DOM representation just flows from that, eliminating the need for events in many cases.



              Barring that, re-emitting would probably be the next best choice, and lastly you might choose to use an event bus as detailed in the other highly voted answer to this question.



              The answer below is my original answer to this question and is not an approach I would take now, having more experience with Vue.





              This is a case where I might disagree with Vue's design choice and resort to DOM.



              In grand-child,



              methods: {
              doEvent() {
              try {
              this.$el.dispatchEvent(new Event("eventtriggered"));
              } catch (e) {
              // handle IE not supporting Event constructor
              var evt = document.createEvent("Event");
              evt.initEvent("eventtriggered", true, false);
              this.$el.dispatchEvent(evt);
              }
              }
              }


              and in parent,



              mounted(){
              this.$el.addEventListener("eventtriggered", () => this.performAction())
              }


              Otherwise, yes, you have to re-emit, or use a bus.



              Note: I added code in the doEvent method to handle IE; that code could be extracted in a reusable way.






              share|improve this answer























              • This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
                – BassMHL
                Mar 7 '17 at 22:39










              • @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
                – Bert
                Mar 7 '17 at 22:45

















              up vote
              20
              down vote



              accepted










              The Vue community generally favors using Vuex to solve this kind of issue. Changes are made to Vuex state and the DOM representation just flows from that, eliminating the need for events in many cases.



              Barring that, re-emitting would probably be the next best choice, and lastly you might choose to use an event bus as detailed in the other highly voted answer to this question.



              The answer below is my original answer to this question and is not an approach I would take now, having more experience with Vue.





              This is a case where I might disagree with Vue's design choice and resort to DOM.



              In grand-child,



              methods: {
              doEvent() {
              try {
              this.$el.dispatchEvent(new Event("eventtriggered"));
              } catch (e) {
              // handle IE not supporting Event constructor
              var evt = document.createEvent("Event");
              evt.initEvent("eventtriggered", true, false);
              this.$el.dispatchEvent(evt);
              }
              }
              }


              and in parent,



              mounted(){
              this.$el.addEventListener("eventtriggered", () => this.performAction())
              }


              Otherwise, yes, you have to re-emit, or use a bus.



              Note: I added code in the doEvent method to handle IE; that code could be extracted in a reusable way.






              share|improve this answer























              • This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
                – BassMHL
                Mar 7 '17 at 22:39










              • @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
                – Bert
                Mar 7 '17 at 22:45















              up vote
              20
              down vote



              accepted







              up vote
              20
              down vote



              accepted






              The Vue community generally favors using Vuex to solve this kind of issue. Changes are made to Vuex state and the DOM representation just flows from that, eliminating the need for events in many cases.



              Barring that, re-emitting would probably be the next best choice, and lastly you might choose to use an event bus as detailed in the other highly voted answer to this question.



              The answer below is my original answer to this question and is not an approach I would take now, having more experience with Vue.





              This is a case where I might disagree with Vue's design choice and resort to DOM.



              In grand-child,



              methods: {
              doEvent() {
              try {
              this.$el.dispatchEvent(new Event("eventtriggered"));
              } catch (e) {
              // handle IE not supporting Event constructor
              var evt = document.createEvent("Event");
              evt.initEvent("eventtriggered", true, false);
              this.$el.dispatchEvent(evt);
              }
              }
              }


              and in parent,



              mounted(){
              this.$el.addEventListener("eventtriggered", () => this.performAction())
              }


              Otherwise, yes, you have to re-emit, or use a bus.



              Note: I added code in the doEvent method to handle IE; that code could be extracted in a reusable way.






              share|improve this answer














              The Vue community generally favors using Vuex to solve this kind of issue. Changes are made to Vuex state and the DOM representation just flows from that, eliminating the need for events in many cases.



              Barring that, re-emitting would probably be the next best choice, and lastly you might choose to use an event bus as detailed in the other highly voted answer to this question.



              The answer below is my original answer to this question and is not an approach I would take now, having more experience with Vue.





              This is a case where I might disagree with Vue's design choice and resort to DOM.



              In grand-child,



              methods: {
              doEvent() {
              try {
              this.$el.dispatchEvent(new Event("eventtriggered"));
              } catch (e) {
              // handle IE not supporting Event constructor
              var evt = document.createEvent("Event");
              evt.initEvent("eventtriggered", true, false);
              this.$el.dispatchEvent(evt);
              }
              }
              }


              and in parent,



              mounted(){
              this.$el.addEventListener("eventtriggered", () => this.performAction())
              }


              Otherwise, yes, you have to re-emit, or use a bus.



              Note: I added code in the doEvent method to handle IE; that code could be extracted in a reusable way.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Jan 8 at 15:32

























              answered Mar 6 '17 at 0:40









              Bert

              43k66279




              43k66279












              • This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
                – BassMHL
                Mar 7 '17 at 22:39










              • @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
                – Bert
                Mar 7 '17 at 22:45




















              • This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
                – BassMHL
                Mar 7 '17 at 22:39










              • @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
                – Bert
                Mar 7 '17 at 22:45


















              This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
              – BassMHL
              Mar 7 '17 at 22:39




              This behaves differently for IE? wasn't aware there were browser discrepancies with vue...
              – BassMHL
              Mar 7 '17 at 22:39












              @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
              – Bert
              Mar 7 '17 at 22:45






              @BassemLhm Vue is fine with IE. The problem with IE is not Vue, it's this is a DOM solution and you cannot do new Event() in IE. You have to document.createEvent(). I can add the IE support if needed.
              – Bert
              Mar 7 '17 at 22:45














              up vote
              16
              down vote













              Yes, you're correct events only go from child to parent. They don't go further, e.g. from child to grandparent.



              The Vue documentation (briefly) addresses this situation in the Non Parent-Child Communication section.



              The general idea is that in the grandparent component you create an empty Vue component that is passed from grandparent down to the children and grandchildren via props. The grandparent then listens for events and grandchildren emit events on that "event bus".



              Some applications use a global event bus instead of a per-component event bus. Using a global event bus means you will need to have unique event names or namespacing so events don't clash between different components.



              Here is an example of how to implement a simple global event bus.






              share|improve this answer

























                up vote
                16
                down vote













                Yes, you're correct events only go from child to parent. They don't go further, e.g. from child to grandparent.



                The Vue documentation (briefly) addresses this situation in the Non Parent-Child Communication section.



                The general idea is that in the grandparent component you create an empty Vue component that is passed from grandparent down to the children and grandchildren via props. The grandparent then listens for events and grandchildren emit events on that "event bus".



                Some applications use a global event bus instead of a per-component event bus. Using a global event bus means you will need to have unique event names or namespacing so events don't clash between different components.



                Here is an example of how to implement a simple global event bus.






                share|improve this answer























                  up vote
                  16
                  down vote










                  up vote
                  16
                  down vote









                  Yes, you're correct events only go from child to parent. They don't go further, e.g. from child to grandparent.



                  The Vue documentation (briefly) addresses this situation in the Non Parent-Child Communication section.



                  The general idea is that in the grandparent component you create an empty Vue component that is passed from grandparent down to the children and grandchildren via props. The grandparent then listens for events and grandchildren emit events on that "event bus".



                  Some applications use a global event bus instead of a per-component event bus. Using a global event bus means you will need to have unique event names or namespacing so events don't clash between different components.



                  Here is an example of how to implement a simple global event bus.






                  share|improve this answer












                  Yes, you're correct events only go from child to parent. They don't go further, e.g. from child to grandparent.



                  The Vue documentation (briefly) addresses this situation in the Non Parent-Child Communication section.



                  The general idea is that in the grandparent component you create an empty Vue component that is passed from grandparent down to the children and grandchildren via props. The grandparent then listens for events and grandchildren emit events on that "event bus".



                  Some applications use a global event bus instead of a per-component event bus. Using a global event bus means you will need to have unique event names or namespacing so events don't clash between different components.



                  Here is an example of how to implement a simple global event bus.







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Mar 6 '17 at 0:10









                  Sly_cardinal

                  8,37333437




                  8,37333437






















                      up vote
                      6
                      down vote













                      Another solution will be:



                      Uses vm.$root.$emit in grand-child, then uses vm.$root.$on at the ancestor (or anywhere you'd like).






                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>








                      share|improve this answer





















                      • Most elegant solution to me.
                        – Ovilia
                        Sep 22 at 7:27















                      up vote
                      6
                      down vote













                      Another solution will be:



                      Uses vm.$root.$emit in grand-child, then uses vm.$root.$on at the ancestor (or anywhere you'd like).






                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>








                      share|improve this answer





















                      • Most elegant solution to me.
                        – Ovilia
                        Sep 22 at 7:27













                      up vote
                      6
                      down vote










                      up vote
                      6
                      down vote









                      Another solution will be:



                      Uses vm.$root.$emit in grand-child, then uses vm.$root.$on at the ancestor (or anywhere you'd like).






                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>








                      share|improve this answer












                      Another solution will be:



                      Uses vm.$root.$emit in grand-child, then uses vm.$root.$on at the ancestor (or anywhere you'd like).






                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>








                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>





                      Vue.component('parent', {
                      template: '<div>I am the parent - {{ action }} <child @eventtriggered="performAction"></child></div>',
                      data(){
                      return {
                      action: 'No action'
                      }
                      },
                      created: function () {
                      this.$root.$on('eventtriggered1', () => {
                      this.performAction()
                      })
                      },
                      methods: {
                      performAction() { this.action = 'actionDone' }
                      }
                      })

                      Vue.component('child', {
                      template: '<div>I am the child <grand-child @eventtriggered="doEvent"></grand-child></div>',
                      methods: {
                      doEvent() {
                      //this.$emit('eventtriggered')
                      }
                      }
                      })

                      Vue.component('grand-child', {
                      template: '<div>I am the grand-child <button @click="doEvent">Do Event</button></div>',
                      methods: {
                      doEvent() { this.$root.$emit('eventtriggered1') }
                      }
                      })

                      new Vue({
                      el: '#app'
                      })

                      <script src="https://unpkg.com/vue/dist/vue.js"></script>

                      <div id="app">
                      <parent></parent>
                      </div>






                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Aug 2 at 20:24









                      Sphinx

                      5,41521228




                      5,41521228












                      • Most elegant solution to me.
                        – Ovilia
                        Sep 22 at 7:27


















                      • Most elegant solution to me.
                        – Ovilia
                        Sep 22 at 7:27
















                      Most elegant solution to me.
                      – Ovilia
                      Sep 22 at 7:27




                      Most elegant solution to me.
                      – Ovilia
                      Sep 22 at 7:27










                      up vote
                      3
                      down vote













                      NEW ANSWER (Nov-2018 update)



                      I discovered that we could actually do this by leveraging the $parent property in the grand child component:



                      this.$parent.$emit("submit", {somekey: somevalue})


                      Much cleaner and simpler.






                      share|improve this answer





















                      • Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                        – Qtax
                        Dec 4 at 17:31















                      up vote
                      3
                      down vote













                      NEW ANSWER (Nov-2018 update)



                      I discovered that we could actually do this by leveraging the $parent property in the grand child component:



                      this.$parent.$emit("submit", {somekey: somevalue})


                      Much cleaner and simpler.






                      share|improve this answer





















                      • Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                        – Qtax
                        Dec 4 at 17:31













                      up vote
                      3
                      down vote










                      up vote
                      3
                      down vote









                      NEW ANSWER (Nov-2018 update)



                      I discovered that we could actually do this by leveraging the $parent property in the grand child component:



                      this.$parent.$emit("submit", {somekey: somevalue})


                      Much cleaner and simpler.






                      share|improve this answer












                      NEW ANSWER (Nov-2018 update)



                      I discovered that we could actually do this by leveraging the $parent property in the grand child component:



                      this.$parent.$emit("submit", {somekey: somevalue})


                      Much cleaner and simpler.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Nov 7 at 16:30









                      BassMHL

                      1,84912341




                      1,84912341












                      • Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                        – Qtax
                        Dec 4 at 17:31


















                      • Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                        – Qtax
                        Dec 4 at 17:31
















                      Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                      – Qtax
                      Dec 4 at 17:31




                      Note that this only works if the relationship is child -> grandparent. This does not work if the child can be nested arbitrary levels deep.
                      – Qtax
                      Dec 4 at 17:31










                      up vote
                      0
                      down vote













                      This is the only case when I use event bus!! For passing data from deep nested child, to not directly parent, communication.




                      First: Create a js file (I name it eventbus.js) with this content:




                      import Vue from 'vue'    
                      Vue.prototype.$event = new Vue()



                      Second: In your child component emit an event:




                      this.$event.$emit('event_name', 'data to pass')



                      Third: In the parent listen to that event:




                      this.$event.$on('event_name', (data) => {
                      console.log(data)
                      })


                      Note: If you don't want that event anymore please unregister it:



                      this.$event.$off('event_name')



                      INFO: No need to read the below personal opinion




                      I don't like to use vuex for grand-child to grand-parent communication (Or similar communication level).




                      In vue.js for passing data from grand-parent to grand-child you can use provide/inject. But there is not something similar for the opposite thing. (grand-child to grand-parent) So I use event bus whenever I have to do that kind of communication.







                      share|improve this answer

























                        up vote
                        0
                        down vote













                        This is the only case when I use event bus!! For passing data from deep nested child, to not directly parent, communication.




                        First: Create a js file (I name it eventbus.js) with this content:




                        import Vue from 'vue'    
                        Vue.prototype.$event = new Vue()



                        Second: In your child component emit an event:




                        this.$event.$emit('event_name', 'data to pass')



                        Third: In the parent listen to that event:




                        this.$event.$on('event_name', (data) => {
                        console.log(data)
                        })


                        Note: If you don't want that event anymore please unregister it:



                        this.$event.$off('event_name')



                        INFO: No need to read the below personal opinion




                        I don't like to use vuex for grand-child to grand-parent communication (Or similar communication level).




                        In vue.js for passing data from grand-parent to grand-child you can use provide/inject. But there is not something similar for the opposite thing. (grand-child to grand-parent) So I use event bus whenever I have to do that kind of communication.







                        share|improve this answer























                          up vote
                          0
                          down vote










                          up vote
                          0
                          down vote









                          This is the only case when I use event bus!! For passing data from deep nested child, to not directly parent, communication.




                          First: Create a js file (I name it eventbus.js) with this content:




                          import Vue from 'vue'    
                          Vue.prototype.$event = new Vue()



                          Second: In your child component emit an event:




                          this.$event.$emit('event_name', 'data to pass')



                          Third: In the parent listen to that event:




                          this.$event.$on('event_name', (data) => {
                          console.log(data)
                          })


                          Note: If you don't want that event anymore please unregister it:



                          this.$event.$off('event_name')



                          INFO: No need to read the below personal opinion




                          I don't like to use vuex for grand-child to grand-parent communication (Or similar communication level).




                          In vue.js for passing data from grand-parent to grand-child you can use provide/inject. But there is not something similar for the opposite thing. (grand-child to grand-parent) So I use event bus whenever I have to do that kind of communication.







                          share|improve this answer












                          This is the only case when I use event bus!! For passing data from deep nested child, to not directly parent, communication.




                          First: Create a js file (I name it eventbus.js) with this content:




                          import Vue from 'vue'    
                          Vue.prototype.$event = new Vue()



                          Second: In your child component emit an event:




                          this.$event.$emit('event_name', 'data to pass')



                          Third: In the parent listen to that event:




                          this.$event.$on('event_name', (data) => {
                          console.log(data)
                          })


                          Note: If you don't want that event anymore please unregister it:



                          this.$event.$off('event_name')



                          INFO: No need to read the below personal opinion




                          I don't like to use vuex for grand-child to grand-parent communication (Or similar communication level).




                          In vue.js for passing data from grand-parent to grand-child you can use provide/inject. But there is not something similar for the opposite thing. (grand-child to grand-parent) So I use event bus whenever I have to do that kind of communication.








                          share|improve this answer












                          share|improve this answer



                          share|improve this answer










                          answered Nov 22 at 16:24









                          roli roli

                          2,455817




                          2,455817






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.





                              Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                              Please pay close attention to the following guidance:


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f42615445%2fvuejs-2-0-emit-event-from-grand-child-to-his-grand-parent-component%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              What visual should I use to simply compare current year value vs last year in Power BI desktop

                              How to ignore python UserWarning in pytest?

                              Alexandru Averescu