Issues including Moment.js library for use with Tabulator in Vue.js

Viewed 1902

I am trying to use the Date Time functionality with Tabulator which requires the moment.js library. In my application before adding Tabulator, moment.js was already being used in certain components that level. I have a new test component that uses Tabulator and attempts to use datetime. Typically I would just import moment and use it here but it seems that moment is required within Tabulator itself.

My first thought is that Moment.js needs to be setup globally in my application so I did that.

Main.js:

```
   import Vue from 'vue'
   import App from './App'
   import router from './router'
   import { store } from './store'
   import Vuetify from 'vuetify'
   import 'vuetify/dist/vuetify.min.css'
   import moment from 'moment'

   Vue.prototype.moment = moment

   ...............

   new Vue({
   el: '#app',
   data () {
    return {
      info: null,
      loading: true,
      errored: false // this.$root.$data.errored
    }
  },
  router,
  components: { App },
  template: '<App/>',
  store
  })

```

In my component (Testpage.vue)

```
<template>
  <div>
    <div ref="example_table"></div>
  </div>
</template>

<script>
// import moment from 'moment'
var Tabulator = require('tabulator-tables')
export default {
  name: 'Test',
  data: function () {
    return {
      tabulator: null, // variable to hold your table
      tableData: [{id: 1, date: '2019-01-10'}] // data for table to display
    }
  },
  watch: {
    // update table if data changes
    tableData: {
      handler: function (newData) {
        this.tabulator.replaceData(newData)
      },
      deep: true
    }
  },
mounted () {
    // instantiate Tabulator when element is mounted
    this.tabulator = new Tabulator(this.$refs.example_table, {
      data: this.tableData, // link data to table
      columns: [
        {title: 'Date', field: 'date', formatter: 'datetime', formatterParams: {inputFormat: 'YYYY-MM-DD', outputFormat: 'DD/MM/YY', invalidPlaceholder: '(invalid date)'}}
      ],
}
</script>
```

I receive the error: "Uncaught (in promise) Reference Error: moment is not defined at Format.datetime (tabulator.js?ab1f:14619)" I am able to use moment in other components by using this.$moment() but I need for it to be available in node_modules\tabulator-tables\dist\js\tabulator.js since thats where the error is happening. Any idea how to include the library?

1 Answers

Go back to the first option you were trying, because annotating the Vue prototype with moment is definitely not the right approach. Even if it was recommended (which it isn't), Tabulator would have to know to find it by looking for Vue.moment. It isn't coded to do that.

One of the things I love about Open Source is that you can see exactly what a library is doing to help fix the issue. A quick search of the Tabulator code base finds this:

https://github.com/olifolkerd/tabulator/blob/3aa6f17b04cccdd36a334768635a60770aa10e38/src/js/modules/format.js

var newDatetime = moment(value, inputFormat);

The formatter is just calling moment directly, without importing it. It's clearly designed around the old-school mechanism of expecting libraries to be available globally. In browser-land that means it's on the "window" object. Two quick options could resolve this:

  1. Use a CDN-hosted version of Moment such as https://cdnjs.com/libraries/moment.js/ by putting something like this in the header of your page template:

    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
    
  2. Adjust your code above to set moment on window:

    window.moment = moment;
    

ohgodwhy's comment above isn't necessarily wrong from the perspective of date-fns being better in many ways. But it won't work for you because Tabulator is hard-coded to look for moment, so you'll need moment itself to work.

Related