Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parent not listening to child $emit - VueJS

Here is the child component:

Vue.component("training-edit", {
    template: "#training-edit-template",
    props: ["show"],
    data: function () {
        return {
            form: new Form(),
            isWorking: false
        }
    },
    watch: {
        show: function (val) {
            if (val) {
                $("#editTrainingModal").modal("show");
            } else {
                $("#editTrainingModal").modal("hide");
            }
        }
    },
    methods: {
        onCancel: function () {
            this.$emit("doneEditing");
        }
    }
});

Here is the parent:

new Vue({
    el: "#trainingEditContainer",
    data: {
        isWorking: false,
        showEditTraining: false
    },
    methods: {
        onEdit: function (e) {
            e.preventDefault();
            this.showEditTraining = true;
        },
        doneEditing: function () {
            this.showEditTraining = false; 
        }
    }
});

HTML:

<div id="trainingEditContainer" class="row">
    // unrelated stuff here

    <training-edit v-bind:show="showEditTraining"></training-edit>
</div>
<script id="training-edit-template" type="x-template">
    <modal-right modalId="editTrainingModal">
        <div class="modal-header">
            <button type="button" class="close" v-on:click="onCancel" aria-label="close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title">Edit Training</h4>
        </div>
        @Html.Partial("Partial/_EditPartial")
    </modal-right>
</script>

I can see in the Vue Developer Tools in Chrome that the event is being emitted but for some reason, the parent is not hearing it and the doneEditing function is never called. Am I missing something obvious here?

like image 787
Quiver Avatar asked Dec 05 '17 18:12

Quiver


1 Answers

First, I recommend you change the name of the event to done-editing.

this.$emit("done-editing")

This is because attributes in HTML are case insensitive and if you are rendering some of your template to the DOM, it's just better all around to avoid camelCased names. Note that this doesn't apply if you define the templates in strings or if you are using single file components.

Then you need to listen for it on the component.

<training-edit @done-editing="doneEditing" v-bind:show="showEditTraining">

When you emit an event from a component, the parent has to explicitly listen for the event.

like image 139
Bert Avatar answered Oct 16 '22 08:10

Bert