nhayder's avatar
Level 13

basic $emit() function not working

Im 2 weeks old when it comes to vue.js im struggling since couple of days ago to make show / hide functionalities for my custome page manager component modal.

on the main app.js i have page manager component like this.

require('./bootstrap');

window.Vue = require('vue');

Vue.component('page-manager', require('./components/PageManager.vue'));


const app = new Vue({

    el: '#app',

    data: {

        //

    },

    methods: {

        showPageManger : function (){
    
         this.$emit('togglePageManager); // im guessing this will emit event to child component ???

    } 

    }

});

this is the page manager component

<template>

<div v-show="isVisible" class="fixed pin">

    <div class="cursor-pointer" @click="togglePageManager">
        <i class="fas fa-times text-2xl text-blue-dark"></i>
    </div>
    // reset of my code goes here 
</div>

</template>

<script>

export default {

  name: 'PageManager',

  data () {

    return {

        isVisible   :               false,
    }

  },

  methods: {

    togglePageManager : function(){

        this.isVisible = !this.isVisible;

    }

  }

}
</script>

the togglePageManger function is working fine withen vue.js component the issue i'm facing is when i added top navigation with permanent button to show/hide vue pageManager component.

// this is the button that should control pageManger component on top navigation

<a href="javascript:void(0)" @click="$emit('showPageManger')">
              <i class="fas fa-bars fa-2x"></i>
</a>

any ideas how to fix this issue ????

0 likes
11 replies
Drfraker's avatar

You need to add an event listener to your vue component. Also, it's easier to read events that are past tense and then respond to them in present tense. 'pageManagerToggled' would be the event that you emit and then your component responds by 'togglePageManager'. The code reads how you would say it, which is nice.

// Assuming this is in a vue compnent...

<a href="javascript:void(0)" @click="$emit('page-manager-toggled')">
              <i class="fas fa-bars fa-2x"></i>
</a>
// add a listener to the component...
<template>

<div v-show="isVisible" class="fixed pin">

    <div class="cursor-pointer" @click="togglePageManager" v-on:page-manager-toggled="togglePageManager">
        <i class="fas fa-times text-2xl text-blue-dark"></i>
    </div>
    // reset of my code goes here 
</div>

</template>

<script>

export default {

  name: 'PageManager',

  data () {

    return {

        isVisible   :               false,
    }

  },

  methods: {

    togglePageManager : function(){

        this.isVisible = !this.isVisible;

    }

  }

}
</script>
1 like
nhayder's avatar
Level 13

@Drfraker i already tried that and its not working, ... not sure what is going on with my app

nhayder's avatar
Level 13

this is the child component where a user can click a button to show PageManager

<template>
    <div class="fixed pin-b pin-r p-5 justify-center">

        <a href="javascript:void(0)"  @click="showPageManager">
           <i class="fas fa-paint-brush"></i>
        </a>
    </div>
</template>

<script>
    export default {

        mounted() {

            //
            
        },

        methods: {

            showPageManager : function(){

                this.$emit('showPage');

            }         
        }

    }
</script>

i added this listener on the pageManger component like this

<template>

  <div 

    v-show="isVisibleR"

    v-on:showTheme="togglePageManager"

    >

      // reset of the code goes here


      </div>

  </div>
        
</template>

<script>

export default {

  name: 'pageManager',

  data () {

    return {

        isVisibleR:false,

        swatchVisible:false,

        primaryColor: 'bg-green',

    }

  },

  methods: { 

    togglePageManager : function(){
      
        this.isVisibleR = !this.isVisibleR;
        
    },  

  }
}
</script>


can anybody see something wrong with my code, coz i'm stucked big time on this.

Drfraker's avatar

First off your emitted events should be kebab-case not camelCase. Secondly, you have $emit('showPage') but you are listening to v-on:showTheme

That is probably the problem.

1 like
nhayder's avatar
Level 13

@Drfraker I updated the code and its still not working, I think i have serious issues with my app but i just cant see them?

sfz0311's avatar

On and emit must be in a same component or vue instance. If you would like to call a child component method from parent, you can add ref=“pagemanager” in parent template and use this.$ref.pagemanager.togglePageManager to call the method.

1 like
nhayder's avatar
Level 13

@sfz0311 this is totally new never head of ref's before, can you please show some code relative to the example above ??? i will updated it from my side. Its just get solid idea on how to do this.

nhayder's avatar
Level 13

This is taking more than usual to get the $emit function to work, Im using vue js with laravel 5.6 as my backend framework.

This is seriously making me worry on how to fix the issue because NOTHING SO FAR HAS FIXED IT, so i will put all the code that i have maybe somebody can suggest a fix.

i have a tools and theme manager component on my main page blade file

<!DOCTYPE html>
<html lang="{{ app()->getLocale() }}" dir="ltr">
<head>
    <title>{{ config('app.name') }}</title>
    <meta charset="UTF-8">
    <meta name="robots" content="noindex,nofollow"/> 
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <link rel="shortcut icon" type="image/x-icon" href="{{ asset('favicon.ico') }}" />
    <meta name="csrf-token" content="{{ csrf_token() }}">

    <link href="{{ mix('/css/designer.css') }}" rel="stylesheet">
    <link href="{{ asset('/css/fontawesome5/css/all.min.css') }}" rel="stylesheet">
    
<body class="bg-blue-lightest font-light leading-normal">
    
    <div id="designer">

        @include('admin.designer.ui.vd-navbar')
        
        @yield('content')

        <theme-manager @theme-requested="showThemeManager"></theme-manager>

        <tools></tools>

    </div>

    <script type="text/javascript" src="{{ mix('/js/designer.js') }}"></script>

</body>

</html>

This is my main js file -> designer.js

require('./bootstrap');

window.Vue = require('vue');
window.swal = require('sweetalert2')

import Tooltip from 'tooltip.js';

Vue.component('theme-manager', require('./components/ThemeManager.vue'));
Vue.component('tools', require('./components/Tools.vue'));

const app = new Vue({

   el: '#designer',

   methods: {

       showThemeManager : function(){

           alert();

       },
   }
});

from tools component i have a button that when clicked it $emits a function to show theme manager component on the page like this

<template>
    <div class="fixed pin-b pin-r p-5 justify-center">
        <a href="javascript:void(0)" class="text-white" @click="openThemeManager">
        </a>
    </div>
</template>

<script>
    export default {

        methods: { 

            openThemeManager: function(){

                this.$emit('theme-requested'); 
            }
        }

    }
</script>

The alert function on the main js file is not getting triggered as expected? so basically its not getting passed from child to parent, not sure what is going on, Just to make it simple i will explain what i did in words

i have 2 components tools and theme-manager component on my app, from tools component i have a button that should show the other component (theme-manager).

1- so in tools component i have a function that triggered when a user clicks the button

 ( this.$emit('theme-requested');  ) 

2- im listening for the event on my main blade page where the root div located id="designer" and where i declared both component (see above)

<theme-manager @theme-requested="showThemeManager"></theme-manager>

<tools></tools>

3- on my main js file i have a function that will show alert('') 
        methods: {

        showThemeManager : function(){
            alert();
        },
    }

4- the alert will be replaced with other function its just for testing the code, 5- the problem is the alert has never be triggered, i just cant make the $emitt() function to work on my app.

I hope sombody have a fix for this, Waiting for assistant ASAP.

Drfraker's avatar

I think you should take a step back and go through the vue 2 course here at laracasts. You are trying to run before you can walk.

1 like
sfz0311's avatar
sfz0311
Best Answer
Level 4

You really should go over the Vue api documents before start writing your code.

Here below is the definition of $emit form Vue api doc. https://vuejs.org/v2/api/

"Trigger an event on the current instance. Any additional arguments will be passed into the listener’s callback function."

So, it clearly says that trigger an event on the current instance. And what you are doing in your code is that you are triggering an event at one instance and listen it at another instance.

In this case, you should add ref where you are using your page manager.

<page-manager ref="pagemanager"></page-manager>

and then in the same instance. you write your showPageManager like below

showPageManager() {
    this.$refs.pagemanager. togglePageManager
}

this.$refs.pagemanager will get the instance of the page manager component, so you can call it's method togglePageManager.

1 like

Please or to participate in this conversation.