olifolkerd / tabulator

Interactive Tables and Data Grids for JavaScript
http://tabulator.info
MIT License
6.77k stars 821 forks source link

require('Tabulator') doesn't work after 4.8.0 version when importing for use with vue.js #2976

Closed EnochG1 closed 4 years ago

EnochG1 commented 4 years ago

Describe the bug I was using extendModules following guide, http://tabulator.info/docs/4.0/upgrade#modules

After upgrade the version of tabulator-tables with npm, Tabulator.prototype.extendModule is not working with below message. image

It seems Tabulator.prototype does not exist anymore. But I couldn't find changed guide of extendModules in 4.8.0 (http://tabulator.info/docs/4.8/modules#extend)

Tabulator Info 4.8.0

Working Example Just check existing of Tabulator.prototype when define const Tabulator = require('tabulator-tables');

Screenshots image

Desktop (please complete the following information):

olifolkerd commented 4 years ago

Hey @EnochG1

I am afraid i am unable to replicate your issue,

The console error suggests that you have not imported Tabulator before calling the extendModule function as it is saying the prototype is undefined, which is only possible if Tabulator does not exist.

Do you have a JS Fiddle that demonstrates the issue?

Cheers

Oli :)

EnochG1 commented 4 years ago

It occurs when using tabulator-tables package with npm so I couldn't replicate by Jsfiddle with unpkg.

When I install tabulator-tables package and define Tabulator with require, const Tabulator = require('tabulator-tables'); then print Tabulator object, result of 4.7.2 and 4.8.0 is different.

image till 4.7.2

image after 4.8.0 (Tabulator.prototype is undefined. It may be changed like Tabulator.default.prototype)

So I think there are some changes with declaring package at version 4.8.0.

olifolkerd commented 4 years ago

Thanks for clarifying that. That makes a lot of sense.

I updated the package to allow ESM import statements, it looks like that is interfering with the require functionality.

I will get a patch out for that ASAP

Cheers

Oli

olifolkerd commented 4 years ago

Hey @EnochG1

Can i ask what development environment you are working it, i cannot seem to replicate your issue. no matter what version of NPM i use i can still continue to import my code using the require statement,

If you are importing the library as a module then you would need to use the import syntax.

It is likely that however you have your environment configured it is using ES2015 module syntax, in which case you would now need to use the import Tabulator from "tabulator-tables syntax

Let me know if that helps

Cheers

Oli :)

EnochG1 commented 4 years ago

Here's my development environment. I'm using vue.js(Not using VueTabulator, but using manually including Tabulator.) and babel (for support IE11) I tested vue-cli compact project and could replicated this issue.

Node : 12.18.0 NPM 6.14.4 (or yarn 1.21.1)

// package.json dependencies
"dependencies": {
        "vue": "^2.6.10"
    },
    "devDependencies": {
        "@vue/cli-plugin-babel": "^3.0.1",
    "@vue/cli-plugin-eslint": "^3.0.1",
    "@vue/cli-service": "^3.0.1",
    "vue-template-compiler": "^2.5.17",
    "tabulator-tables": "^4.8.0"
    }

Test code just like http://tabulator.info/docs/4.8/frameworks#vue > Manually Including Tabulator

olifolkerd commented 4 years ago

How are you importing Tabulator into your project?

Are you using require?

Are you importing it globally and referencing it from another file.or are you importing it into a specific component?

Are you using is files or mjs?

ComicShrimp commented 4 years ago

Same issue here, I'm using Vue-Tabulator and importing Tabulator to extend the keybindings. I'm importing tabulator-tables in the main.js and using the code below, but Vue didn't load the page:

Tabulator.prototype.extendModule('keybindings', 'bindings', {
  navRight: '39',
  navLeft: '37',
});

After removing this code, Vue was able to load, but said that tabulator is not a constructor and failed to load the tables.

olifolkerd commented 4 years ago

What would be really helpful is if someone could provide me with a single file involving the import of tabulator and the attempt to extend it that fails on your machine along with a description of the environment you are trying to do it on.

This will be related to the new ESM import functionality i added in the latest release, but i am unable to replicate your issue on my end, so a single file with all the necessary code would really help me out.

Have any of you tried replacing your existing require statements with a import Tabulator from "tabulator-tables" to see if that helps, it would be really useful if someone could give me feedback on whether that works, if it does it would point to exactly where the issue lies.

Cheers

Oli

ComicShrimp commented 4 years ago

Here's my main.js file for Tabulator 4.7.2:

// Files
import App from './App.vue';
import router from './router/index';
import store from './store/index';

// Libraries
import { BootstrapVue, BootstrapVueIcons } from 'bootstrap-vue';
import Loading from 'vue-loading-overlay';
import Multiselect from 'vue-multiselect';
import Vue from 'vue';
import VueSweetalert2 from 'vue-sweetalert2';
import VueTabulator from 'vue-tabulator';
import VueTheMask from 'vue-the-mask';

// Others
import './style/index.scss';
import '@babel/polyfill';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-vue/dist/bootstrap-vue.css';
import 'mutationobserver-shim';
import 'sweetalert2/dist/sweetalert2.min.css';
import 'vue-multiselect/dist/vue-multiselect.min.css';
import 'vue-loading-overlay/dist/vue-loading.css';

var Tabulator = require('tabulator-tables');

// Tabulator Config.
Tabulator.prototype.extendModule('keybindings', 'bindings', {
  navRight: '39',
  navLeft: '37',
});

Tabulator.prototype.extendModule('keybindings', 'actions', {
  // Navegação para cima
  navUp: function(event) {
    event.preventDefault(); // Previne o comportamento padrão de scroll

    let linhas_selecionadas = this.table.getSelectedRows();
    if (!linhas_selecionadas.length) return;

    let lastSelectedRow = linhas_selecionadas[linhas_selecionadas.length - 1];
    let upRow = lastSelectedRow.getPrevRow();

    if (!upRow) return;

    this.table.deselectRow();
    this.table.selectRow(upRow);
    this.table.scrollToRow(upRow, 'top', false);
  },
  navDown: function(event) {
    event.preventDefault(); // Previne o comportamento padrão de scroll

    let linhas_selecionadas = this.table.getSelectedRows();
    if (!linhas_selecionadas.length) return;

    let lastSelectedRow = linhas_selecionadas[linhas_selecionadas.length - 1];
    let downRow = lastSelectedRow.getNextRow();

    if (!downRow) return;

    this.table.deselectRow();
    this.table.selectRow(downRow);
    this.table.scrollToRow(downRow, 'bottom', false);
  },
  navRight: function(event) {
    event.preventDefault();

    let linhas_selecionadas = this.table.getSelectedRows();
    if (!linhas_selecionadas.length) return;

    let selectedRow = linhas_selecionadas[linhas_selecionadas.length - 1];

    try {
      if (selectedRow.getTreeChildren().length <= 0) return;

      selectedRow.treeExpand();
    } catch {
      return;
    }
  },
  navLeft: function(event) {
    event.preventDefault();

    let linhas_selecionadas = this.table.getSelectedRows();
    if (!linhas_selecionadas.length) return;

    let selectedRow = linhas_selecionadas[linhas_selecionadas.length - 1];

    try {
      if (selectedRow.getTreeChildren().length <= 0) return;

      selectedRow.treeCollapse();
    } catch {
      return;
    }
  },
});

Vue.use(BootstrapVue);
Vue.use(BootstrapVueIcons);
Vue.use(VueTabulator);
Vue.use(VueTheMask);
Vue.use(VueSweetalert2);
Vue.component('loading', Loading);
Vue.component('multiselect', Multiselect);

Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
  router,
  store,
}).$mount('#app');

Using this way I got an error saying: Tabulator.prototype is undefined Modifying the import from var Tabulator = require('tabulator-tables'); to import Tabulator from "tabulator-tables"; I got an Vue warn Error in mounted hook: "TypeError: Tabulator is not a constructor" in the pages i use Tabulator.

P.S: I didn't know where to send the file, so I pasted here. And sorry for not send the file before, I'm new in creating issues :)

EnochG1 commented 4 years ago

@olifolkerd, I just followed your doc code.

image doc code.

<template>
  <div ref="table"></div>
</template>

<script>
var Tabulator = require("tabulator-tables"); //import Tabulator library

export default {
  name: 'app',
  data: function () {
    return {
      tabulator: null, //variable to hold your table
      tableData: [], //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.table, {
      data: this.tableData, //link data to table
      reactiveData:true, //enable data reactivity
      columns: [], //define table columns
    });
  }
}
</script>

my code I copied it at App.vue.

and in main.js, used render $mount like ComicShrimp. (

import App from './App.vue';
import Vue from 'vue';
new Vue({
  render: h => h(App)
}).$mount('#app');

I already checked changing require to import is working. So we can just focus about 'require' because if it doesn't work with vue.js you should modify documentation or fix bug.

olifolkerd commented 4 years ago

Hey @EnochG1

So just to confirm as your statement was a bit ambiguous, when does it work properly, when using import or when using require

Cheers

Oli

EnochG1 commented 4 years ago

@olifolkerd, If you test my or ComicShrimp's code, you can replicate issue with require('Tabulator').

  1. Using require, can't access Tabulator.prototype, console.log(Tabulator); shows Module object. (from 4.8.0)
  2. Using import, new Tabulator() or Tabulator.prototype works, like using require till 4.7.2. (console.log(Tabulator) shows json object like 4.7.2 screenshot) but your doc's code at 4.8.0 shows like require is working with vue.js

It occurs when using tabulator-tables package with npm so I couldn't replicate by Jsfiddle with unpkg.

When I install tabulator-tables package and define Tabulator with require, const Tabulator = require('tabulator-tables'); then print Tabulator object, result of 4.7.2 and 4.8.0 is different.

image till 4.7.2

image after 4.8.0 (Tabulator.prototype is undefined. It may be changed like Tabulator.default.prototype)

So I think there are some changes with declaring package at version 4.8.0.

EnochG1 commented 4 years ago

I added test project in my repository.

https://github.com/EnochG1/vue-tabulator-test

you can replicate issue just running npm install in terminal and npm run serve I could replicate this issue not only with vue-cli, but with vue and webpack.

olifolkerd commented 4 years ago

Hey @EnochG1

I will update the docs then, It looks like now that i have added ESM support when you start importing modules like that for view it forces webpack to take the ESM route into the module.

I will update the example and include a note in the release notes and upgrade guide.

Cheers

Oli :)