Tyler Morales
Tyler Morales

Reputation: 1830

Error: "Error in v-on handler: "TypeError: this.filter is undefined"" in a list rendering in vue?

I am trying to build a component that creates filter buttons and then sends the type attribute in the filters object through the event bus to be handled elsewhere in my app. However, when I added the array of objects (filters) in the data section, I am getting an error of this.filter is not defined when I click on a button.

I would like to keep the filters array in this component because I am also trying to dynamically change the active class to whichever button has been clicked.

Am I missing something that has to do with props? Why am I unable to display the buttons when the data and v-for was on another component? These were the questions I have been asking myself in order of solving this issue.

<template>
  <div>
    <button
      v-for="(filter, index) in filters"
      :key="index"
      :class="{ active: index === activeItem }"
      @click="emitFilter(), selectItem(index)"
      :filter="filter"
    >
      {{ filter.name }}
    </button>
  </div>
</template>

<script>
import EventBus from '@/components/EventBus'
export default {
  props: {
    filter: { type: String }
  },
  data() {
    return {
      activeItem: 0,
      filterResult: '',
      filters: [
        { name: 'All', type: 'all' },
        { name: 'Holidays', type: 'holiday' },
        { name: 'Seasons', type: 'season' },
        { name: 'Events', type: 'custom' }
      ]
    }
  },
  methods: {
    emitFilter() {
      this.filterResult = this.filter
      EventBus.$emit('filter-catagories', this.filterResult)
    },
    selectItem(index) {
      this.activeItem = index
    }
  }
}
</script>

My button component is used in a filters component

<template>
  <div>
    <span>filters</span>
      <FilterBtn />
    </div>
  </div>
</template>

<script>
import FilterBtn from '@/components/FilterBtn'


export default {
  components: {
    FilterBtn
      }
  // data() {
  //   return {
  //     filters: [
  //       { name: 'All', type: 'all' },
  //       { name: 'Holidays', type: 'holiday' },
  //       { name: 'Seasons', type: 'season' },
  //       { name: 'Events', type: 'custom' }
  //     ]
  //   }
  // }
}
</script>

As you can see, the commented section is where I had my filters originally, but I had to move them to the button component in order to add the active class.

Upvotes: 0

Views: 631

Answers (3)

tony19
tony19

Reputation: 138336

I'm assuming you were actually trying to access the filter iterator of v-for="(filter, index) in filters" from within emitFilter(). For this to work, you'd need to pass the filter itself in your @click binding:

<button v-for="(filter, index) in filters"
        @click="emitFilter(filter)">

Then, your handler could use the argument directly:

export default {
  methods: {
    emitFilter(filter) {
      this.filterResult = filter
      //...
    }
  }
}

Upvotes: 1

Ilijanovic
Ilijanovic

Reputation: 14914

Yea you dont pass an prop to your component thats why its undefined.

<FilterBtn filter="test" />

Here i pass an prop named filter with the value of test.

Sure you could pass dynamic props. Just bind it.

<FilterBtn :filter="yourData" />

I need to ask: Are you passing an object or an string?

Because you defined your prop to be a string, but you actually use it as an object

  {{ filter.name }}

Maybe you should also set the type to Object.

  props: {
    filter: { type: Object }
  },

Upvotes: 0

andypotato
andypotato

Reputation: 722

You are passing a prop called filter typed string to your component. When you output {{ filter.name }} you are actually referring to this property instead of the variable filter you create within the v-for loop.

Unless you passed a property called "filter" to your component, this property will be undefined. Therefore outputting filter.name will result in this error message.

Upvotes: 0

Related Questions