Daniel F
Daniel F

Reputation: 14239

Using $emit to call a function

I'm new to vue.js and am trying to understand how $emit can be used. In the following code, every input element except for the last one works as expected.

My assumption in the last input element is that calling $emit with an event name would be the same as calling the function which has that event name, but it doesn't call that function. What is occurring with this $emit?

I've read through Binding Native Events to Components and that shows that it is to be used differently as I'm doing it. All this approach started from me watching a YouTube video (7 Secret Patterns...), specifically at this time https://youtu.be/7lpemgMhi0k?t=21m57s where you can see that usage on the slide.

Here is the code in JSFiddle https://jsfiddle.net/sbtmfweq/

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>


<div id="test-app">
  <input v-model="text1" placeholder="edit me" @keyup.enter="submit"> {{ text1 }}
  <br><br>
  <input :value="text2" @input="inputEvent" @keyup.enter="submit"> {{ text2 }}
  <br><br>
  <input :value="text2" @input="inputEvent($event)" @keyup.enter="submit"> {{ text2 }}
  <br><br>
  <input :value="text2" @input="$emit('inputEvent', $event.target.value)"> {{ text2 }} | {{reversedText2}}
</div>

<script>

  new Vue({
    el: '#test-app',
    data: {
      text1: 'text1',
      text2: 'text2',
    },
    methods: {
      log: console.log,
      submit: function(event) {
        console.log("submit -->", event, event.target.value, '<--')
      },
      inputEvent: function(event) {
        console.log("input 2 -->", event.target.value, '<--')
        this.text2 = event.target.value
      },
    },
    watch: {
      text1: {
        handler: function(newValue, oldValue) {
          console.log("input 1 -->", newValue, '<-->', oldValue, '<--')
        }
      }
    },
    computed: {
      reversedText2: function () {
        return this.text2.toUpperCase()
      }
    }
  })

</script>

Upvotes: 1

Views: 6055

Answers (3)

Thomas Lombart
Thomas Lombart

Reputation: 433

it's normal that $emit doesn't work in your case.

In fact, $emit is used for communication between parent and child components. Here, you are using $emit but you haven't defined any parent component.

Here is the docs for the custom events.

Hope it helps!

Upvotes: 0

Decade Moon
Decade Moon

Reputation: 34306

$emit works like this.

Say you have 2 components, <parent> and <child>, where <child> is inside <parent>'s template.

When <child> emits an event, it can be handled by the <parent> component only (unless you register a listener via $on, but that's unrelated to your scenario). In your code, the $emit call is executed within the scope of the parent component (which is the root component instantiated with new Vue()); that is, the parent component is the one that's emitting the event. The root component has no parent so the emit call is pointless.

My assumption in the last input element is that calling $emit with an event name would be the same as calling the function which has that event name, but it doesn't call that function.

This isn't true; the name of the event has no relation to the method registered as a listener for that event in the parent.

Upvotes: 1

Ankit Kumar Ojha
Ankit Kumar Ojha

Reputation: 2384

It's just a simple issue. Whenever you are dispatching an event, you have to add listener to it. In $emit, the first param is actually the name of the event.

As written in docs for $emit.

vm.$emit( eventName, […args] )

In the below code, I have added an event listener, using $on. Also I have changed the arg for $emit.

  <input :value="text2" @input="$emit('inputEvent', $event)"> {{ text2 }} | {{reversedText2}}

<script>

  new Vue({
    ...
    created(){
        this.$on('inputEvent', this.inputEvent);
    }
    ...
  })

</script>

I hope it helps.

Upvotes: 3

Related Questions