Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does `this` inside filter() gets undefined in VueJS?

Tags:

vue.js

vuejs2

I am creating a DOB Form.

I am using VueJS in the form. The user should their date of month first so that day is displayed according to the number of days in the respective month.

I am using filter() and the problem is this inside filter() is undefined. How can I fix this?

new Vue ({
  el: '.app',
  data: {
    months: [
      {month: 'January', days: 31},
      {month: 'February', days: 28},
      {month: 'March', days: 31},
      {month: 'April', days: 30},
      {month: 'May', days: 31},
      {month: 'June', days: 30},
      {month: 'July', days: 31},
      {month: 'August', days: 31},
      {month: 'September', days: 30},
      {month: 'October', days: 31},
      {month: 'November', days: 30},
      {month: 'December', days: 31},
    ],
    selectedMonth: []
  },
  computed: {
    filterDays() {
      return this.months.filter(function(value) {
        return value.month === this.selectedMonth;
      });
    }
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div class="app">
  <select id="dobd">
    <option v-for="day in filterDays[0].days" :value="day">{{ day }}</option>
	</select>
</div>

I know using a global variable might be the solution but I want to use selectedMonth inside data() due to my own needs.

like image 819
Sanjay Avatar asked Apr 08 '18 03:04

Sanjay


People also ask

Where can Vue filters be applied?

Vue Filters differ from computed properties in two ways. Going off number 2, because VueJS filters are meant for text transformations, they can only be used in two places: mustache interpolations (the curly braces in your template) and in v-bind expressions.

What is this keyword in VUE JS?

The this keyword within Vue gives you easy access to all of your data and functionalities. Wether you want to access a data property, a computed property, a component prop or a function, you can all find them directly on the this keyword.


1 Answers

With function () {} the context (this) is lost. Which means, inside the filter argument function, this will not be the Vue instance.

There are some possible solutions:

  • Use arrow functions (preferred):

    filterDays() {
      return this.months.filter((value) => {
        return value.month === this.selectedMonth;
      });
    }
    
  • Use .bind():

    filterDays() {
      return this.months.filter(function(value) {
        return value.month === this.selectedMonth;
      }.bind(this));
    }
    
  • Use a local variable outside the function:

    filterDays() {
      let vm = this;
      return this.months.filter(function(value) {
        return value.month === vm.selectedMonth;
      });
    }
    

Demo:

new Vue ({
  el: '.app',
  data: {
    months: [
      {month: 'January', days: 31},
      {month: 'February', days: 28},
      {month: 'March', days: 31},
      {month: 'April', days: 30},
      {month: 'May', days: 31},
      {month: 'June', days: 30},
      {month: 'July', days: 31},
      {month: 'August', days: 31},
      {month: 'September', days: 30},
      {month: 'October', days: 31},
      {month: 'November', days: 30},
      {month: 'December', days: 31},
    ],
    selectedMonth: 'January' // changed to a valid month
  },
  computed: {
    filterDays() {
      return this.months.filter((value) => {
        return value.month === this.selectedMonth;
      });
    }
  },
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>

<div class="app">
  <select id="dobd">
    <option v-for="day in filterDays[0].days" :value="day">{{ day }}</option>
  </select>
</div>
like image 94
acdcjunior Avatar answered Oct 23 '22 06:10

acdcjunior