Richard Barraclough
Richard Barraclough

Reputation: 2964

VueJS passing computed value from component to parent

I've made a VueJS component that operates some <select> elements. The result of this UI is that the user selects a value.

I have a function in the compoent's computed for showing the user's selected value on screen.

How do I pass this value back to the parent VueJS thingy?

It seems to be something to so with $emit but I don't see that I have an event.

I've tied to raise one as suggested here, but nowt happens.

In the component:

        computed: {
            selectedCode: function () {
                var selected = '(No code selected.)';
                if (this.category) { selected = this.category; }
                if (this.code) { selected = this.code; }

                this.$emit('selectedCode', selected);

                return selected;
            },

In the parent Vue app:

<code-selector v-bind:code="code" v-on:selectedCode="codeSelect"></sic-selector>

and

                methods:
                {
                    selectedCode: function (z) {
                        console.log(z);
                    },

Upvotes: 1

Views: 3768

Answers (1)

palaѕн
palaѕн

Reputation: 73916

The issue here is mainly because of emitting a camelCased event name. So, as mentioned in the docs:

If emitting a camelCased event name:

this.$emit('myEvent')

Listening to the kebab-cased version will have no effect:

<!-- Won't work -->
<my-component v-on:my-event="doSomething"></my-component>

Unlike components and props, event names will never be used as variable or property names in JavaScript, so there’s no reason to use camelCase or PascalCase. Additionally, v-on event listeners inside DOM templates will be automatically transformed to lowercase (due to HTML’s case-insensitivity), so v-on:myEvent would become v-on:myevent – making myEvent impossible to listen to.

For these reasons, we recommend you always use kebab-case for event names.

So, just emit a kebab-case event name like:

this.$emit('selected-code', selected);

and then you can easily listen to it like:

<code-selector v-on:selected-code="codeSelect"></code-selector>

Here is a working demo:

Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ getCount }} times.</button>',
  computed: {
     getCount: function () {
        this.$emit('selected-code', this.count);
        return this.count;
     }
  }
})


new Vue({
  el: "#myApp",
  data: {},
  methods: {
    codeSelect(z) {
      console.clear()
      console.log(z);
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js"></script>
<div id="myApp">
  <button-counter v-on:selected-code="codeSelect"></button-counter>
</div>

Note: Please note that the demo shared in the answer in the question that you have shared in your post Can I get computed data from child component to parent component? on codepen, has a simple emitted event name like:

this.$emit('update', e.target.valueAsNumber)

Thus the code is working in that demo.

Upvotes: 6

Related Questions