1
votes

I have a child component which emits an event in the created function

created: function(){
    this.$emit('onPageTitleChange', this.pageTitle);

    this.updateList()
}

i have this inside the #app div (that I'm assinging the vue instance to):

<h2 class="no-margin-bottom" v-on:onPageTitleChange="updatePageTitle">{{ pageTitle }}</h2>

and the vue app (the parent) has the upatePageTitle defined as:

methods: {
    updatePageTitle(title){
        this.pageTitle = title;
    }
},

The page title is not changing - what am I missing?

1
The listener has to be on the component that emits the event. The listener above is on an h2 element. - Bert
I thought the parent (in this case the vue app) could listen for all events? - user3791372
See this example. The parent is listening; but it has to listen in the right place. You can't just randomly place the listener. codepen.io/Kradek/pen/BmygBx?editors=1010 - Bert
ok, I understand that, but my content is being loaded by the router, and so I tried adding the event listener to router-view to no joy - user3791372
You may be running into an issue with kebab-case vs camel-case. Look at the example now. - Bert

1 Answers

6
votes

There were two issues here. First, the listener needs to be defined in the parent on the component that is emitting the event. Given a router is being used (as pointed out in comments) the listener can be added to the router-view.

<router-view @on-page-title-change="updatePageTitle"></router-view>

Second, when a template is defined in DOM, meaning, not a string or single file component template, then you need to be aware of camelCase vs kebab-case issues. Attributes in HTML are case-insensitive. I find it best simply to avoid ever emitting camelCased events. That being the case, emit a kebab-cased event.

this.$emit('on-page-title-change', this.pageTitle);

And listen to it as shown above.

Here is a working example.

console.clear()

const Foo = { 
  template: '<div>foo</div>',
  created() {
    this.$emit("on-page-title-change", "This is the Foo title")
  }
}
const Bar = { template: '<div>bar</div>' }

const routes = [
  { path: '/', component: Foo },
  { path: '/bar', component: Bar }
]

const router = new VueRouter({
  routes // short for `routes: routes`
})



new Vue({
  el: "#app",
  router,
  data:{
    pageTitle: "This is the original title"
  },
  methods: {
    updatePageTitle(title){
      this.pageTitle = title;
    }
  },
})
<script src="https://unpkg.com/[email protected]"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>

<div id="app">
  <h2>{{pageTitle}}</h2>
  <router-view @on-page-title-change="updatePageTitle"></router-view>
</div>