Home > Software engineering >  TypeError: Cannot read properties of undefined in Vue
TypeError: Cannot read properties of undefined in Vue

Time:10-29

I am beginner web developer. I make my first project in VUE.

I have this code:

<script type="text/ecmascript-6">
import axios from 'axios';
import Vue from 'vue';
import 'vuejs-datatable/dist/themes/bootstrap-4.esm';
import {
  VuejsDatatableFactory,
  IDataFnParams,
  IDisplayHandlerParam,
  ITableContentParam,
  TColumnsDefinition,
  VueDatatable
} from 'vuejs-datatable';

Vue.use(VuejsDatatableFactory, VueDatatable);
import Swal from 'sweetalert2';

export default {
  props: {
    fetchUrl: {type: String, required: true},
    columns: {type: Array, required: true},
    headers: {type: Object, required: true},
    routeName: {type: String, required: true},
    showUrl: {type: String, required: false},
  },
  data() {
    return {
      tableData: [],
      url: '',
      pagination: {
        meta: {to: 1, from: 1}
      },
      offset: 4,
      currentPage: 1,
      perPage: 100,
      sortedColumn: this.columns[0],
      order: 'asc',
      search: '',
      pageOptions: [100, 200, 500, 1000],
    }
  },
  watch: {
    fetchUrl: {
      handler: function (fetchUrl) {
        this.url = fetchUrl
      },
      immediate: true
    }
  },
  created() {
    console.log(this.fetchUrl);
    return this.fetchData()
  },
  computed: {
    /**
     * Get the pages number array for displaying in the pagination.
     * */
    pagesNumber() {
      if (!this.pagination.meta.to) {
        return []
      }
      let from = this.pagination.meta.current_page - this.offset
      if (from < 1) {
        from = 1
      }
      let to = from   (this.offset * 2)
      if (to >= this.pagination.meta.last_page) {
        to = this.pagination.meta.last_page
      }
      let pagesArray = []
      for (let page = from; page <= to; page  ) {
        pagesArray.push(page)
      }
      return pagesArray
    },
    /**
     * Get the total data displayed in the current page.
     * */
    totalData() {
      return (this.pagination.meta.to - this.pagination.meta.from)   1
    }
  },
  methods: {
    fetchData() {
      let dataFetchUrl = `${this.url}&page=${this.currentPage}&column=${this.sortedColumn}&order=${this.order}&per_page=${this.perPage}&search=${this.search}`
      axios.get(dataFetchUrl)
        .then(({data}) => {
          this.pagination = data
          this.tableData = data.data
        }).catch(error => this.tableData = [])
    },
    /**
     * Get the serial number.
     * @param key
     * */
    serialNumber(key) {
      return (this.currentPage - 1) * this.perPage   1   key
    },
    /**
     * Change the page.
     * @param pageNumber
     */
    changePage(pageNumber) {
      this.currentPage = pageNumber
      this.fetchData()
    },
    /**
     * Sort the data by column.
     * */
    sortByColumn(column) {
      if (column === this.sortedColumn) {
        this.order = (this.order === 'asc') ? 'desc' : 'asc'
      } else {
        this.sortedColumn = column
        this.order = 'asc'
      }
      this.fetchData()
    },
    handleSearch() {
      this.fetchData()
    },
    handlePerPage($event) {
      this.perPage = $event.target.value;
      this.fetchData()
    },

    recordLink(id) {
      return this.routeName   `/${id.toString()}`
    },
    editRecordLink(id) {
      return this.routeName   `/${id.toString()}/edit`
    },
    showRecord(id) {
      const recordLink = this.recordLink(id);
      this.$router.push({path: recordLink});
    },
    editRecord(id) {
      const editRecordLink = this.editRecordLink(id);
      this.$router.push({path: editRecordLink});
    },
    deleteRecord(id) {
      let self = this;
      axios.post(this.$apiAdress   '/api/'   this.routeName   '/'   id   '?token='   localStorage.getItem("api_token"), {
        _method: 'DELETE'
      })
        .then(function (response) {
          Swal.fire(
            'Sukces!',
            'Rekord usunięty poprawnie!',
            'success'
          )
          self.fetchData();
        }).catch(function (error) {
        console.log(error);
        self.$router.push({path: '/login'});
      });
    },
    prepareRemove(id){
      const removeId = id;
      Swal.fire({
        title: 'Czy na pewno',
        text: "Chcesz usunąć ten rekord?",
        type: 'warning',
        showCancelButton: true,
        confirmButtonColor: '#d33',
        cancelButtonColor: '#3085d6',
        confirmButtonText: 'Tak, usuń!',
        cancelButtonText: 'Anuluj',
        buttonsStyling: true
      }).then(function (isConfirm) {
        if(isConfirm.value === true) {
          this.deleteRecord(removeId);
        }
      });
    }


    ///
  },
  filters: {
    columnHead(value) {
      return value.split('_').join(' ').toUpperCase()
    }
  },
  name: 'DataTable'
}
</script>

It's work fine. I have problem with prepareRemove(id). When I run this function after click on link <button @click="prepareRemove(data.id)">

I have sweetalert with question (it's ok). After confirm I have error:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'deleteRecord')

How can I repair it?

CodePudding user response:

This is an issue related with the this binding. It's a common mistake to write a function declaration as a callback inside methods option. I'll recommend using arrow functions in those cases.

Swal.fire({
  title: 'Czy na pewno',
  text: "Chcesz usunąć ten rekord?",
  type: 'warning',
  showCancelButton: true,
  confirmButtonColor: '#d33',
  cancelButtonColor: '#3085d6',
  confirmButtonText: 'Tak, usuń!',
  cancelButtonText: 'Anuluj',
  buttonsStyling: true
  }).then((isConfirm) => {
    // now 'this' depends on the lexical enviroment.
    if(isConfirm.value === true) {
      this.deleteRecord(removeId);
    }
});
  • Related