25

I've recently started working with VueJS, I'm using v3 and seem to be having an issue calling a method on a parent. The emit function in the child doesn't seem to be emitting the event and nothing is getting picked up in the parent.

I've included the parent and child to show how I have it set up

Parent

<template>
  <First/>
  < Child v-bind:sample="sample" @enlarge-text="onEnlargeText"/>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import axios from 'axios';
import First from './First.vue';
import Child from './Child.vue';

export default defineComponent({
  name: 'Container',
  components: {
    First,
    Child,
  },
  methods: {
    onEnlargeText() {
      console.log('enlargeText');
    },
  },
  data: () => ({
    sample: [],
    parentmessage: '',
  }),
  created() {
    axios.get('http://localhost:8080/getData')
      .then((response) => {
        console.log(response);
        this.sample = response.data;
      })
      .catch((error) => {
        console.log(error);
      });
  },
});
</script>

Child

<template>
  <div id="add">
    <form id="signup-form" @submit.prevent="submit">
      <label for="text">Text:</label>
      <input type="text" v-model="text" required>
      <p class="error" >{{ error }}</p>
      <div class="field has-text-right">
        <button type="submit" class="button is-danger">Submit</button>
      </div>
    </form>
    <button v-on:click="tryThis">
      Enlarge text
    </button>
</div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';
import axios from 'axios';

interface SampleInterface {
  text: string;
  error: string;
}

export default defineComponent({
  name: 'Add',
  data: (): AddInterface => ({
    text: '',
    error: '',
  }),
  methods: {
    tryThis() {
      this.$emit('enlarge-text');
    },
    submit() {
      this.$emit('enlarge-text');
    },
  },
});
</script>

How should this be done? Is there something I've missed?

I was wondering can I still use $emit here?

Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
Keith Darragh
  • 439
  • 1
  • 6
  • 13

2 Answers2

37

You should add the new emits option containing the emitted event names :

child :

<template>
  <div id="child">
    <button v-on:click="tryThis">Enlarge text</button>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "Child",
  emits: ["enlargeText"],
  methods: {
    tryThis() {
      console.log("trying");
      this.$emit("enlargeText", "someValue");
    },
  },
});
</script>

or with script setup syntax :

<template>
  <div id="child">
    <button v-on:click="tryThis">Enlarge text</button>
  </div>
</template>

<script lang="ts">

 const emit= defineEmits(["enlargeText"])
 
  function tryThis() {
      console.log("trying");
      emit("enlargeText", "someValue");
    }

</script>

Parent :

<template>
  <div>
    <p>Container</p>
    <Child @enlargeText="onEnlargeText" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import Child from "./Child.vue";

export default defineComponent({
  name: "UrlContainer",
  components: {
    Child,
  },
  methods: {
    onEnlargeText() {
      console.log("enlarging text");
    },
  },
});
</script>

LIVE DEMO

tony19
  • 125,647
  • 18
  • 229
  • 307
Boussadjra Brahim
  • 82,684
  • 19
  • 144
  • 164
0

Or could use v-model and update event:

// ChildComponent.vue
<template>
  <div>
    <input type="button" @click="increment" value="Click" />
    childCounter: {{ childCounter }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      childCounter:0
    }
  },
  methods: {
    increment() {
      // emit custom update event to update the parent value
      this.$emit('update:childCounter', ++this.childCounter);
    }
  }
}
</script>
// ParentComponent.vue
<template>
  <div>
    <!-- basically means:
      <Child :childCounter="parentCounter" 
             @update:childCounter="(childCounter) => parentCounter = childCounter"
    />
    -->
    <Child v-model:childCounter="parentCounter"></Child>
    parentCounter: {{ parentCounter }}<br/>
  </div>
</template>

<script>
import Child from './ChildComponent.vue'

export default {
  components: {
    Child
  },
  data() {
    return {
      parentCounter: 0
    }
  },
}
</script>
Rohim Chou
  • 907
  • 10
  • 16