简体   繁体   中英

TypeError: Cannot read property '$http' of undefined - VUEJS

I can't access this.$http in filters:

<v-sheet height="500">
  <v-calendar :now="today" :value="today">
    <template v-slot:day="{ date }">
      <template v-for="event in eventsMap[date]">
        <v-menu :key="event.Ref" full-width offset-x>
          <template v-slot:activator="{ on }">
            <div v-ripple v-  v-on="on" >{{event | searchActivity}}</div>                    
          </template>
        </v-menu>
      </template>
    </template>
  </v-calendar>
</v-sheet>

Here is my JavaScript code:

import Vue from "vue";
Vue.filter("searchActivity", function(val) {
  var params = {
    ProblemsID: val.ActivityRef
  };
  this.$http
    .post(auth.API_URL + "api/Problems/Activity", params, {
      headers: {
        Authorization: "Bearer " + auth.getAuthHeader()
      }
    })
    .then(
      response => {
        this.activityList = response.body;
      },
      response => {
        if (response.Status === true) {
          this.text1 = response.body.ResponseMessage;
          this.snackbar = true;
        } else {
          this.text1 = response.statusText;
          this.snackbar = true;
        }
      }
    );
  this.Obj = this.activityList.ActivityName;

  return this.Obj;
});

To quote from the Vue.js docs:

Vue.js allows you to define filters that can be used to apply common text formatting.

Vue.js filters do not have access to this as they are pure functions. Meaning you can't use any injections inside filters.

Furthermore, filters must be synchronous, meaning you can't do HTTP calls or anything async inside them.

Filters are normally used to format text values like money, numbers, date or other common presentable information.

To solve your issue, you cannot use computed either. Because they must be synchronous as well, so you are only left with methods . But you also can't just call an asynchronous method in the template, so you should map your data first before displaying them. You can do the mapping inside mounted or created life-cycle methods.

EDIT: added example

I feel like a lot is going on in your template, I suggest you split the iteration item to a component, let's call it EventDayView :

<template>
  <v-menu :key="event.Ref" full-width offset-x>
    <template v-slot:activator="{ on }">
      <div v-ripple v-on="on">{{ activityList.ActivityName }}</div>                    
    </template>
  </v-menu>
</template>

<script>
export default {
  name: 'EventsDayView',
  props: {
    event: { type: Object, required: true }
  },
  data: () => ({
    activityList: null
  }),
  methods: {
    searchActivity (val) {
      // Your search activity API call
    }
  },
  mounted() {
    this.searchActivity(this.event).then(response => {
      this.activityList = response.body;
    });
  }
};
</script>

Later on you could use it like this:

<v-sheet height="500">
  <v-calendar :now="today" :value="today">
    <template v-slot:day="{ date }">
      <template v-for="event in eventsMap[date]">
        <EventDayView :key="event.Ref" :event="event" />
      </template>
    </template>
  </v-calendar>
</v-sheet>

You really ought to think about components first than reaching out to smaller stuff like filters or directives usually components are what you need.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM