suchislife
suchislife

Reputation: 1

On button click inside component, call parent method. How?

Below, is a functional App containing 3 notify() methods.

The first notify() method is found in component index.

The second notify() method is found in component sign-in.

The third notify() method is found in parent App instance.

Question:

How do I call the third notify() found in parent App instance from the sign-in button click?

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Simple Vue.js Router Example</title>

    <!-- VUE JS v2.6.1 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <!-- VUE ROUTER JS v3.1.3 -->
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <!-- BOOTSTRAP CSS v4.3.1 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <!-- GOOGLE FONT CSS - Roboto Mono -->
    <link href="https://fonts.googleapis.com/css?family=Roboto+Mono:100,300,400,500,700&display=swap" rel="stylesheet">
    <!-- GOOGLE FONT CSS - Material Icons -->
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <!-- CSS -->

    <style type="text/css">

      body {
        font-family: 'Roboto Mono', monospace;
        font-weight: 400;
        font-size: 1rem;
        background-color: #d7ccc8;
      }

      .active {
        color: MediumSeaGreen;
      }

      .exactActive {
        color: #e57373;
      }

    </style>

  </head>

  <body>

    <!--  
      HTML

    -->
    <!-- VUE APP - PARENT CONTAINER -->
    <div id="app" class="container">

      <!-- HEADER CONTAINER -->
      <header>

        <!--  
          LINKS

        -->
        <!-- ROUTER LINK(S) -->
        <ul>
          <li>
            <router-link tag="a" to="/" exact>/index</router-link>
          </li>
          <li>
            <router-link tag="a" to="/sign-in">/sign-in</router-link>
          </li>

        </ul>

        <!--  
          VIEWS

        -->
        <!-- ANY OF THESE CAN/DO OR DO NOT RENDER -->
        <!-- DEPENDS ON ROUTER-LINK SELECTED -->

        <router-view name="RTV_index"></router-view>
        <router-view name="RTV_sign_in"></router-view>

      </header>

    </div>

    <!--  
      JAVASCRIPT

    -->

    <!-- JAVA SCRIPT -->
    <script type="text/javascript">

      // DISABLE
      Vue.config.productionTip = false;
      // DISABLE
      Vue.config.devtools = false;


      /*
        COMPONENTS

      */

      // COMPONENT INDEX
      const CPT_index = { 

        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #bcaaa4;">
          <strong>Component:</strong> CPT_index
          <br>
          <strong>Route :</strong> ./
          <br>
          <strong>Params:</strong> none
          <br>
          <button type="button" v-on:click="notify()">NOTIFY</button>
        </div>
        `,
        // COMPONENT SIGN IN - METHODS
        methods:{
          notify: function() {
            console.log('Hi! I am a method inside a local component CPT_index.');
          }
        }

      };

      // COMPONENT SIGN IN
      const CPT_sign_in = { 

        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #bcaaa4;">
          <strong>Component:</strong> CPT_sign_in
          <br>
          <strong>Route :</strong> ./sign-in
          <br>
          <strong>Params:</strong> none
          <br>
          <button type="button" v-on:click="notify()">NOTIFY</button>
        </div>
        `,
        // COMPONENT SIGN IN - METHODS
        methods:{
          notify: function() {
            console.log('Hi! I am a method inside a local component CPT_sign_in.');
          }
        }


      };

      // COMPONENT 404
      const CPT_404 = { 

        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #ef9a9a;">
          <strong>CPT_404</strong>
          <br>
          <strong>Route :</strong> ./404
          <br>
          <strong>Params:</strong> none
        </div>
        `
      }

      /*
        ROUTER

      */
      // VUE.JS ROUTER INSTANCE
      const router = new VueRouter({

      // IN THIS ROUTE I WILL RENDER THESE COMPONENTS..

        // ROUTER MODE - hash, history
        mode: 'hash',

        base: '/',

        // CSS FOR ROUTER-LINK ACTIVE
        linkActiveClass: "active",
        // CSS FOR ROUTER-LINK exact ACTIVE
        linkExactActiveClass: "exactActive",

        // ROUTES(S) TO EVALUATE IN ORDER
        routes: [

          /*
            ROUTES

          */
          // ROUTE INDEX
          { name: 'index',
            path: '/',
            // ROUTE(S) WITH COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_index: CPT_index,
            }
          }, // END ROUTE INDEX

          // --------------------------------------------------------------------------------

          // ROUTE SIGN IN
          { name: 'sign_in',
            path: '/sign-in',
            // ROUTE(S) WITH COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_sign_in: CPT_sign_in,
            }
          }, // END ROUTE SIGN IN

          // --------------------------------------------------------------------------------

          /*
            REDIRECT

          */
          // ROUTE REDIRECT
          { name: null,
            path: '*', redirect: { name: '404' },
            // TRAP ANY UNDEFINED ROUTE AND...
            // FORWARD IT TO /404 ROUTE
          }, // END ROUTE REDIRECT


          /*
            TO /404

          */
          // ROUTE 404
          { name: '404',
            path: '/404',
            // ROUTE COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_404: CPT_404,
            }
          }, // END ROUTE 404

        ] // END ROUTES(S) TO EVALUATE IN ORDER

      });



      /*
       APP

      */
      // VUE.JS APP INSTANCE
      const App = new Vue({
        // ROOT ELEMENT
        el: '#app',
        // ROUTER
        router,

        /*
          DATA

        */
        // APP DATA (SINGLE SOURCE OF TRUTH)
        data: {
          data0: true,
          data1: 'Data1 - Rendered successfuly.',
          data2: 'Data2 - Rendered successfuly.',
          data3: 'Data3 - Rendered successfuly.',

        },

        /*
          COMPUTED

        */
        // COMPUTED PROPERTIES
        computed: {


        },

        /*
          METHODS

        */
        // APP METHODS
        methods:{
          //Initialize App.
          init: function() {
            
            console.log('App initialized.');

            if (this.supportsLocalSessionStorage()) {
              console.log('HTML5 localStorage & sessionStorage Supported.');
            } else {
              console.error('Fatal Error: No HTML5 localStorage & sessionStorage support.');
            }

          },

          // HTML5 Local & Session sotrage detection
          supportsLocalSessionStorage: function() {
            return typeof(Storage) !== 'undefined';
          },

          notify: function() {
            console.log('Hi! I am a method inside the parent instance App.');
          }

        }, // END APP METHODS

        /*
          HOOKS

        */
        // APP LIFE CYCLE HOOKS
        mounted(){
          this.$nextTick(function () {
            // Code that will run only after the
            // entire view has been rendered
            // Initialize App
            this.init();
          })

        }

      });


    </script>

  </body>

</html>

Upvotes: 1

Views: 144

Answers (2)

suchislife
suchislife

Reputation: 1

I have updated the original example to reflect all changes. We now have a prototype event bus, and components and methods were relabeled for clarity. This functional example should give you a basic understanding of Vue router, routes, local components, event bus and a simple axios get request.

I have added ASCII comments that look great if you have SublimeText 3.

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Simple Vue.js Router Example</title>

    <!-- VUE JS v2.6.1 -->
    <script src="https://unpkg.com/vue/dist/vue.js"></script>
    <!-- VUE ROUTER JS v3.1.3 -->
    <script src="https://unpkg.com/vue-router/dist/vue-router.js"></script>
    <!-- AXIOS JS v0.19.0 -->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <!-- BOOTSTRAP CSS v4.3.1 -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <!-- GOOGLE FONT CSS - Roboto Mono -->
    <link href="https://fonts.googleapis.com/css?family=Roboto+Mono:100,300,400,500,700&display=swap" rel="stylesheet">
    <!-- GOOGLE FONT CSS - Material Icons -->
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

    <!-- CSS -->

    <style type="text/css">

      body {
        font-family: 'Roboto Mono', monospace;
        font-weight: 400;
        font-size: 1rem;
        background-color: #d7ccc8;
      }

      .active {
        color: MediumSeaGreen;
      }

      .exactActive {
        color: #e57373;
      }

    </style>

  </head>

  <body>

    <!-- 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
                                                                                                               
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
     -->

    <!--  
      ##     ## ######## ##     ## ##       
      ##     ##    ##    ###   ### ##       
      ##     ##    ##    #### #### ##       
      #########    ##    ## ### ## ##       
      ##     ##    ##    ##     ## ##       
      ##     ##    ##    ##     ## ##       
      ##     ##    ##    ##     ## ######## 

    -->
    <!-- VUE APP - PARENT CONTAINER -->
    <div id="app" class="container">

      <!-- HEADER CONTAINER -->
      <header>
        <hr>
        <h4>Static Nav</h4>
        <p>by router-link</p>

        <!--  
          ########   #######  ##     ## ######## ######## ########     ##       #### ##    ## ##    ##  ######  
          ##     ## ##     ## ##     ##    ##    ##       ##     ##    ##        ##  ###   ## ##   ##  ##    ## 
          ##     ## ##     ## ##     ##    ##    ##       ##     ##    ##        ##  ####  ## ##  ##   ##       
          ########  ##     ## ##     ##    ##    ######   ########     ##        ##  ## ## ## #####     ######  
          ##   ##   ##     ## ##     ##    ##    ##       ##   ##      ##        ##  ##  #### ##  ##         ## 
          ##    ##  ##     ## ##     ##    ##    ##       ##    ##     ##        ##  ##   ### ##   ##  ##    ## 
          ##     ##  #######   #######     ##    ######## ##     ##    ######## #### ##    ## ##    ##  ######  

        -->
        <!-- ROUTER LINK(S) -->
        <ul>
          <li>
            <router-link tag="a" to="/" exact>/index</router-link>
          </li>
          <li>
            <router-link tag="a" to="/sign-in">/sign-in</router-link>
          </li>
          <li>
            <router-link tag="a" to="/404">/404</router-link>
          </li>

        </ul>

        <!--  
          ########   #######  ##     ## ######## ######## ########     ##     ## #### ######## ##      ##  ######  
          ##     ## ##     ## ##     ##    ##    ##       ##     ##    ##     ##  ##  ##       ##  ##  ## ##    ## 
          ##     ## ##     ## ##     ##    ##    ##       ##     ##    ##     ##  ##  ##       ##  ##  ## ##       
          ########  ##     ## ##     ##    ##    ######   ########     ##     ##  ##  ######   ##  ##  ##  ######  
          ##   ##   ##     ## ##     ##    ##    ##       ##   ##       ##   ##   ##  ##       ##  ##  ##       ## 
          ##    ##  ##     ## ##     ##    ##    ##       ##    ##       ## ##    ##  ##       ##  ##  ## ##    ## 
          ##     ##  #######   #######     ##    ######## ##     ##       ###    #### ########  ###  ###   ######  

        -->
        <!-- ANY OF THESE CAN/DO OR DO NOT RENDER -->
        <!-- RELATIVE TO ROUTER-LINK CURRENTLY SELECTED -->

        <router-view name="RTV_index"></router-view>
        <router-view name="RTV_sign_in"></router-view>

        <router-view name="RTV_404"></router-view>

      </header>

    </div>

    <!-- 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
                                                                                                               
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
      ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
     -->

    <!--  
            ##    ###    ##     ##    ###        ######   ######  ########  #### ########  ######## 
            ##   ## ##   ##     ##   ## ##      ##    ## ##    ## ##     ##  ##  ##     ##    ##    
            ##  ##   ##  ##     ##  ##   ##     ##       ##       ##     ##  ##  ##     ##    ##    
            ## ##     ## ##     ## ##     ##     ######  ##       ########   ##  ########     ##    
      ##    ## #########  ##   ##  #########          ## ##       ##   ##    ##  ##           ##    
      ##    ## ##     ##   ## ##   ##     ##    ##    ## ##    ## ##    ##   ##  ##           ##    
       ######  ##     ##    ###    ##     ##     ######   ######  ##     ## #### ##           ##    

    -->
    <!-- JAVA SCRIPT -->
    <script type="text/javascript">

      // DISABLE
      Vue.config.productionTip = false;
      // DISABLE
      Vue.config.devtools = false;

      /*
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 

        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        
      */

      /*
         ######   #######  ##     ## ########   #######  ##    ## ######## ##    ## ########  ######  
        ##    ## ##     ## ###   ### ##     ## ##     ## ###   ## ##       ###   ##    ##    ##    ## 
        ##       ##     ## #### #### ##     ## ##     ## ####  ## ##       ####  ##    ##    ##       
        ##       ##     ## ## ### ## ########  ##     ## ## ## ## ######   ## ## ##    ##     ######  
        ##       ##     ## ##     ## ##        ##     ## ##  #### ##       ##  ####    ##          ## 
        ##    ## ##     ## ##     ## ##        ##     ## ##   ### ##       ##   ###    ##    ##    ## 
         ######   #######  ##     ## ##         #######  ##    ## ######## ##    ##    ##     ######  

      */
      // COMPONENT INDEX
      const componentIndex = { 

        // HTML TEMPLATE
        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #bcaaa4;">
          <strong>Component:</strong> componentIndex
          <br>
          <strong>Route :</strong> ./
          <br>
          <strong>Params:</strong> none
          <br>
          <button type="button" v-on:click="componentMethod1()">componentMethod1()</button>
        </div>
        `,
        // COMPONENT SIGN IN - DATA
        data: function () {
          return {
            componentDataInt: 0,
            componentDataString: 'A',
            componentDataArray: [],
            componentDataObject: {},
          }
        },
        // COMPONENT SIGN IN - METHODS
        methods:{
          componentMethod1: function() {
            console.info('componentMethod1() inside local componentIndex called.');
          }
        }

      };

      // COMPONENT SIGN IN
      const componentSignIn = { 

        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #bcaaa4;">
          <strong>Component:</strong> componentSignIn
          <br>
          <strong>Route :</strong> ./sign-in
          <br>
          <strong>Params:</strong> none
          <br>
          <button type="button" v-on:click="componentMethod1()">componentMethod1() -> appMethod1()</button>
        </div>
        `,
        // COMPONENT DATA
        data: function () {
          return {
            componentDataInt: 0,
            componentDataString: 'A',
            componentDataArray: [],
            componentDataObject: {},
          }
        },
        // COMPONENT SIGN IN - METHODS
        methods:{
          // COMPONENT METHOD 1
          componentMethod1: function() {
            // EMIT A CALL TO A PARENT APP METHOD
            // this approach assures that our components remain decoupled from the app
            // so they can be re-used.
            // eg. We do not use $parent.appMenthod1() inside the button click; we instead, 
            // emmit a call to this app method using our Vue prototype Event Bus.
            console.info('componentMethod1() inside local componentSignIn called.');
            this.$appEventBus.$emit('appMethod1');
          }
        }

      };

      // COMPONENT 404
      const component404 = { 

        template: 
        `
        <!-- HTML PARENT CONTAINER -->
        <div style="background-color: #ef9a9a;">
          <strong>Component:</strong> component404
          <br>
          <strong>Route :</strong> ./404
          <br>
          <strong>Params:</strong> none
        </div>
        `,
        // COMPONENT DATA
        data: function () {
          return {
            componentDataInt: 0,
            componentDataString: 'A',
            componentDataArray: [],
            componentDataObject: {},
          }
        },
        // COMPONENT 404 - METHODS
        methods:{
          // COMPONENT METHOD 404
          componentMethod404: function() {
            // DEBUG
            console.log('componentMethod404 called.');
          }
        }

      };


      /*
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        
      */


      /*
        ########   #######  ##     ## ######## ######## ########  
        ##     ## ##     ## ##     ##    ##    ##       ##     ## 
        ##     ## ##     ## ##     ##    ##    ##       ##     ## 
        ########  ##     ## ##     ##    ##    ######   ########  
        ##   ##   ##     ## ##     ##    ##    ##       ##   ##   
        ##    ##  ##     ## ##     ##    ##    ##       ##    ##  
        ##     ##  #######   #######     ##    ######## ##     ## 

      */
      // VUE.JS ROUTER INSTANCE
      const router = new VueRouter({

      // IN THIS ROUTE I WILL RENDER THESE COMPONENTS..

        // ROUTER MODE - hash, history
        mode: 'hash',

        base: '/',

        // CSS FOR ROUTER-LINK ACTIVE
        linkActiveClass: "active",
        // CSS FOR ROUTER-LINK exact ACTIVE
        linkExactActiveClass: "exactActive",

        // ROUTES(S) TO EVALUATE IN ORDER
        routes: [

          /*
            ########   #######  ##     ## ######## ########  ######  
            ##     ## ##     ## ##     ##    ##    ##       ##    ## 
            ##     ## ##     ## ##     ##    ##    ##       ##       
            ########  ##     ## ##     ##    ##    ######    ######  
            ##   ##   ##     ## ##     ##    ##    ##             ## 
            ##    ##  ##     ## ##     ##    ##    ##       ##    ## 
            ##     ##  #######   #######     ##    ########  ######  

          */

          // --------------------------------------------------------------------------------

          // ROUTE INDEX
          { name: 'index',
            path: '/',
            // ROUTE(S) WITH COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_index: componentIndex,
            }
          }, // END ROUTE INDEX

          // --------------------------------------------------------------------------------

          // ROUTE SIGN IN
          { name: 'sign_in',
            path: '/sign-in',
            // ROUTE(S) WITH COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_sign_in: componentSignIn,
            }
          }, // END ROUTE SIGN IN

          // --------------------------------------------------------------------------------

          /*
            ########  ######## ########  #### ########  ########  ######  ######## 
            ##     ## ##       ##     ##  ##  ##     ## ##       ##    ##    ##    
            ##     ## ##       ##     ##  ##  ##     ## ##       ##          ##    
            ########  ######   ##     ##  ##  ########  ######   ##          ##    
            ##   ##   ##       ##     ##  ##  ##   ##   ##       ##          ##    
            ##    ##  ##       ##     ##  ##  ##    ##  ##       ##    ##    ##    
            ##     ## ######## ########  #### ##     ## ########  ######     ##    

          */
          // ROUTE REDIRECT
          { name: null,
            path: '*', redirect: { name: '404' },
            // TRAP ANY UNDEFINED ROUTE AND...
            // FORWARD IT TO /404 ROUTE
          }, // END ROUTE REDIRECT

          // --------------------------------------------------------------------------------

          /*
            ########  #######           ## ##          #####   ##        
               ##    ##     ##         ##  ##    ##   ##   ##  ##    ##  
               ##    ##     ##        ##   ##    ##  ##     ## ##    ##  
               ##    ##     ##       ##    ##    ##  ##     ## ##    ##  
               ##    ##     ##      ##     ######### ##     ## ######### 
               ##    ##     ##     ##            ##   ##   ##        ##  
               ##     #######     ##             ##    #####         ##  

          */
          // ROUTE 404
          { name: '404',
            path: '/404',
            // ROUTE COMPONENT(S) TO RENDER IN ORDER
            components: {
              // ONE OR MORE...
              RTV_404: component404,
            }
          }, // END ROUTE 404

        ] // END ROUTES(S) TO EVALUATE IN ORDER

      });


      /*
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## 
        
      */


      /*
           ###    ########  ########  
          ## ##   ##     ## ##     ## 
         ##   ##  ##     ## ##     ## 
        ##     ## ########  ########  
        ######### ##        ##        
        ##     ## ##        ##        
        ##     ## ##        ##        

      */
      // Implement an appEventBus to capture events 
      // ...from anywhere in our application.
      // We make it available to each Vue instance by
      // ...defining them on the prototype:
      Vue.prototype.$appEventBus = new Vue();

      // VUE.JS APP INSTANCE
      const App = new Vue({

        // ROOT ELEMENT
        el: '#app',

        // ROUTER
        router,

        // --------------------------------------------------------------------------------

        /*
             ###    ########  ########     ########     ###    ########    ###    
            ## ##   ##     ## ##     ##    ##     ##   ## ##      ##      ## ##   
           ##   ##  ##     ## ##     ##    ##     ##  ##   ##     ##     ##   ##  
          ##     ## ########  ########     ##     ## ##     ##    ##    ##     ## 
          ######### ##        ##           ##     ## #########    ##    ######### 
          ##     ## ##        ##           ##     ## ##     ##    ##    ##     ## 
          ##     ## ##        ##           ########  ##     ##    ##    ##     ## 

        */
        // APP DATA (SINGLE SOURCE OF TRUTH)
        data: {
          dataInt: 0,
          dataString: 'A',
          dataArray: [],
          dataObject: {},


        },

        // --------------------------------------------------------------------------------

        /*
           ######   #######  ##     ## ########  ##     ## ######## ######## ########  
          ##    ## ##     ## ###   ### ##     ## ##     ##    ##    ##       ##     ## 
          ##       ##     ## #### #### ##     ## ##     ##    ##    ##       ##     ## 
          ##       ##     ## ## ### ## ########  ##     ##    ##    ######   ##     ## 
          ##       ##     ## ##     ## ##        ##     ##    ##    ##       ##     ## 
          ##    ## ##     ## ##     ## ##        ##     ##    ##    ##       ##     ## 
           ######   #######  ##     ## ##         #######     ##    ######## ########  

        */
        // COMPUTED PROPERTIES
        computed: {
          // INFO...
          computed1: function() {
            return true;
          }

        },

        // --------------------------------------------------------------------------------

        /*
          ##      ##    ###    ########  ######  ##     ## 
          ##  ##  ##   ## ##      ##    ##    ## ##     ## 
          ##  ##  ##  ##   ##     ##    ##       ##     ## 
          ##  ##  ## ##     ##    ##    ##       ######### 
          ##  ##  ## #########    ##    ##       ##     ## 
          ##  ##  ## ##     ##    ##    ##    ## ##     ## 
           ###  ###  ##     ##    ##     ######  ##     ## 

        */
        // WATCH PROPERTIES
        wath: {
          // INFO...
          watch1: function() {
            return true;
          }

        },

        // --------------------------------------------------------------------------------

        /*
          ##     ## ######## ######## ##     ##  #######  ########   ######  
          ###   ### ##          ##    ##     ## ##     ## ##     ## ##    ## 
          #### #### ##          ##    ##     ## ##     ## ##     ## ##       
          ## ### ## ######      ##    ######### ##     ## ##     ##  ######  
          ##     ## ##          ##    ##     ## ##     ## ##     ##       ## 
          ##     ## ##          ##    ##     ## ##     ## ##     ## ##    ## 
          ##     ## ########    ##    ##     ##  #######  ########   ######  

        */
        // APP METHODS
        methods:{
          // INITIALIZE APP
          init: function() {
            
            // DEBUG
            console.log('App initialized.');

            // HTML5 - LOCAL & SESSION STORAGE CHECK
            if (this.supportsLocalSessionStorage()) {
              // DEBUG
              console.log('HTML5 localStorage & sessionStorage Supported.');
            } else {
              // DEBUG
              console.error('Fatal Error: No HTML5 localStorage & sessionStorage support.');
            }

          },

          // HTML5 - LOCAL & SESSION STORAGE DETECTION
          supportsLocalSessionStorage: function() {
            return typeof(Storage) !== 'undefined';
          },
          // APP METHOD 1
          appMethod1: function(event) {
            // DEBUG
            console.log('appMethod1() called.');
            console.info('axios request started...');
            // AXIOS GET REQUEST
            axios.get('https://jsonplaceholder.typicode.com/users')
              // handle success
              .then(function (response) { 
                console.info('axios response:');

                // LOOP THORUGH RESPONDE DATA ARRAY OF OBJECTS
                response.data.forEach(function (item, index) {
                    // DEBUG
                    console.log(index, item.name);
                });


              })
              // handle error
              .catch(function (error) { 
                console.error('axios error:', error); 
              })
              // always executed
              .finally(function ()  { 
                console.info('axios request complete.'); 
              });
          }

        }, // END APP METHODS

        // --------------------------------------------------------------------------------

        /*
          ##       #### ######## ########     ######  ##    ##  ######  ##       ######## 
          ##        ##  ##       ##          ##    ##  ##  ##  ##    ## ##       ##       
          ##        ##  ##       ##          ##         ####   ##       ##       ##       
          ##        ##  ######   ######      ##          ##    ##       ##       ######   
          ##        ##  ##       ##          ##          ##    ##       ##       ##       
          ##        ##  ##       ##          ##    ##    ##    ##    ## ##       ##       
          ######## #### ##       ########     ######     ##     ######  ######## ######## 


          ##     ##  #######   #######  ##    ##  ######  
          ##     ## ##     ## ##     ## ##   ##  ##    ## 
          ##     ## ##     ## ##     ## ##  ##   ##       
          ######### ##     ## ##     ## #####     ######  
          ##     ## ##     ## ##     ## ##  ##         ## 
          ##     ## ##     ## ##     ## ##   ##  ##    ## 
          ##     ##  #######   #######  ##    ##  ######  

        */
        // APP LIFE CYCLE HOOKS
        mounted(){
          // Our mounted hook doesn’t guarantee that the whole component tree renders.
          // so we use nextTick
          this.$nextTick(function () {
            // The whole view is now rendered, so we can safely access or query
            // the DOM.
            // Initialize App
            this.init();
          });

          // EventBus now listening for $emit('appMethod1')
          // coming from ANY v-on:event ANYwhere.
          this.$appEventBus.$on('appMethod1', (event) => {
            // DEBUG
            console.log('EventBus used to call a parent method.');
            // CALL APP METHOD 1
            this.appMethod1();
          });

        },

        // --------------------------------------------------------------------------------

      });


    </script>

  </body>

</html>

Upvotes: 0

Tim Wickstrom
Tim Wickstrom

Reputation: 5701

To achieve what you are looking for you would simply change:

<button type="button" v-on:click="notify()">NOTIFY</button>

to

<button type="button" v-on:click="$parent.notify()">NOTIFY</button>

However, since the "parent" is the $root component you can actually call:

<button type="button" v-on:click="$root.notify()">NOTIFY</button>

Which will get around the following gotcha of using parent. When calling $parent you are coupling your component hierarchy which will make it difficult to reuse these components. You may want to consider an event driving system using $emit.

<button type="button" v-on:click="$emit('notify')">NOTIFY</button>

Then on any parent component you would listen for 'notify' like this:

mounted () {
  this.$on('notify', (event) => {
    // do something in your case it would be
    this.notify()
  })
}

You may want to also consider implementing an event bus to capture events from anywhere in your application.

A simple example of this would be:

In main.js add:

Vue.prototype.$bus = new Vue

In a component add:

<button type="button" v-on:click="$bus.$emit('notify')">NOTIFY</button>

Then in any other component you can add:

mounted () {
  this.$bus.$on('notify', (event) => {
    // do something in your case it would be
  })
}

Hope this helps!

Upvotes: 3

Related Questions