Chelsey Machin
Chelsey Machin

Reputation: 11

PointerEvent object being returned instead of child data on emit

I am working on creating a vue component library. I have build a button component that has data of it's width and left position. I'm trying to emit that data to the parent (a tabs component) when it's clicked. I have troubleshooted quite a bit, and have narrowed down most of the problem. My child component (button) is emitting the correct thing, but it looks like the parent component (tabs) is receiving the value of the click/pointerevent object instead of the data passed on the emit. I'm certain this is some issue in my parent click handle method, but can't pinpoint what exactly. I've included code snippets for the components and their click handler methods.

This is pared down, but essentially, I want to emit the width (and eventually left position) of the child button to the parent tab upon clicking the child/button. I want to assign that emitted width/left position to the slider to move some reactive underlining whenever a button is clicked in the tabs. I built in a console log statement on the click event that returns the emitted value from the child, and then returns the received value from the parent. Right now, the child is emitting the correct value when button is clicked, but parent is receiving and trying to assign a PointerEvent object. Thanks for any feedback!

Child (button) template and relevant script:

<template>
  <div class="button @click="click" ref="button"> 
    <slot />
  </div>
</template>

<script>
import { ref } from 'vue'
  export default {
    name: 'Button',
    emits: [
      'click'
    ],
    data () {
      return {
        width: '',
        left: ''
      }
    },
    setup() {
      const button = ref(null)

      return {
        button
      }
    },
    mounted () {
      this.$nextTick(() => {
        this.left = Math.ceil(this.button.getBoundingClientRect().left)
        this.width = Math.ceil(this.button.getBoundingClientRect().width)
      })
    },
    methods: {
      click () {
        this.$emit('click', this.width)
        console.log(`${this.width} has been emitted to the tabs component`)
      }
    }
  }
</script>

Parent (tab) template and relevant script:

<template>
  <div class="tabs" @click="updateSliderWidth">
    slot
  </div>
  <div class="slider" :style="sliderWidth">
</template>

<script>
import Button from './Button.vue'

export default {
  name: 'Tabs',
  components: {
   Button
  },
  methods: {
    updateSliderWidth (value) {
      this.sliderWidth = value
      console.log(`${value} has been received and assigned by parent`)
    }
  },
  data () {
    return {
      sliderWidth: ''
    }
  }
}
</script>

Upvotes: 1

Views: 8808

Answers (1)

tho-masn
tho-masn

Reputation: 1174

I can't see any problems with your code, except that you don't use the Button component in the parent component. Instead you are using a div. This would explain, why you're getting a PointerEvent. This Event is passed as first parameter to the event, if you don't pass anything explicitly.

Here a demo: https://stackblitz.com/edit/vue-opruyd?file=src%2FApp.vue

Upvotes: 3

Related Questions