ratiw / vuetable-2

data table simplify! -- datatable component for Vue 2.x. See documentation at
https://vuetable.com
MIT License
2.16k stars 400 forks source link

All callback functions fail #261

Open hanxue opened 6 years ago

hanxue commented 6 years ago

I am using:

vuetable-2: 1.6.6 vue: 2.3.4

I just wrote a dummy statusName() callback as per the example, and the result is no value appears

<script>
export default {
    data () {
        return {
            fields: [
                // other fields appear OK, removed for berevity
                {
                    name: 'shot_version',
                    sortField: 'shot_status_name',
                    title: 'Status',
                    titleClass: 'center aligned',
                    dataClass: 'center aligned',
                    callback: 'statusName'
                },
            ],
        }
    },
    methods: {
        statusName(value) {
          return value.toUpperCase()
        },
        onPaginationData(paginationData) {
            this.$refs.paginationTop.setPaginationData(paginationData),
            this.$refs.paginationInfoTop.setPaginationData(paginationData),

            this.$refs.pagination.setPaginationData(paginationData),
            this.$refs.paginationInfo.setPaginationData(paginationData)
        },
        onChangePage(page) {
            this.$refs.vuetable.changePage(page)
        },
        onAction(action, data, index) {
            console.log('custom-actions: ' + action, data.name, index)
        },
        onCellClicked(data, field, event) {
            this.$refs.vuetable.toggleDetailRow(data.shot_id)
        }
    }
}
</script>

Without the callback, the value displays fine in the column. With the callback, nothing appears. I have tried changing the callback to really basic, such as returning 'Hello World!', but nothing seems to work.

My intention is something like this:

status_name(value) {
            switch (value[0].shot_status_name) {
              case 'Ready':
                 return '<span class="ui label"><md-icon>fiber_new</md-icon></span>'
                case 'Submit':
                 return '<span class="ui label"><md-icon>input</md-icon></span>'
                case 'Publish':
                 return '<span class="ui label"><md-icon>cloud_done</md-icon></span>'
             }
        },

Is there anyway to troubleshoot the callback function? I tried using console.log() inside a callback function, but it does not output anything.

ratiw commented 6 years ago

@hanxue Everything is still working on my end. I don't know why it doesn't work for you. Can you please try remove node_modules and reinstall with npm install?

hanxue commented 6 years ago

@ratiw Many thanks for your assistance and prompt reply. As you suggested, I have deleted node_modules and reinstalled all dependencies using npm install

If it helps, I am using npm 5.2.0 because of an issue with 5.4.x, and this is my package.json

{
    "name": "My App",
    "version": "0.1.0",
    "description": "My App description",
    "author": "My Company",
    "license": "UNLICENSED",
    "repository": {
        "type": "git",
        "url": "server.com/project.git"
    },
    "main": "main.js",
    "scripts": {
        "dev-server": "cross-env NODE_ENV=development webpack-dev-server",
        "dev": "cross-env NODE_ENV=development electron ./",
        "build": "cross-env NODE_ENV=production webpack --progress --profile --colors",
        "start": "cross-env NODE_ENV=production electron ./",
        "package": "npm run build; npm run package-osx; npm run package-win; npm run package-linux;",
        "package-osx": "electron-packager ./ --platform=darwin --arch=x64 --icon=assets/app.icns --out=package --asar=true --overwrite=force",
        "package-win": "electron-packager ./ --platform=win32 --arch=ia32 --icon=assets/app.ico --out=package --asar=true --overwrite=force",
        "package-linux": "electron-packager ./ --platform=linux --arch=ia32 --icon=assets/app.ico --out=package --asar=true --overwrite=force"
    },
    "dependencies": {
        "accounting": "^0.4.1",
        "electron": "^1.6.11",
        "electron-packager": "^8.7.2",
        "material-design-icons": "^3.0.1",
        "moment": "^2.18.1",
        "semantic-ui-css": "^2.2.12",
        "vue": "^2.3.4",
        "vue-axios": "^2.0.2",
        "vue-material": "^0.7.4",
        "vue-router": "^2.5.3",
        "vuetable-2": "^1.6.6",
        "vuex": "^2.4.0"
    },
    "devDependencies": {
        "babel-core": "^6.25.0",
        "babel-loader": "^7.1.1",
        "babel-plugin-transform-runtime": "^6.23.0",
        "babel-preset-env": "^1.6.0",
        "babel-preset-es2015": "^6.24.1",
        "babel-preset-stage-2": "^6.24.1",
        "chalk": "^2.1.0",
        "clean-webpack-plugin": "^0.1.16",
        "copy-webpack-plugin": "^4.0.1",
        "cross-env": "^5.0.1",
        "css-loader": "^0.28.4",
        "cssnano": "^3.10.0",
        "electron-reload": "^1.2.1",
        "eslint-friendly-formatter": "^3.0.0",
        "extract-text-webpack-plugin": "^3.0.0",
        "file-loader": "^0.11.2",
        "friendly-errors-webpack-plugin": "^1.6.1",
        "html-webpack-plugin": "^2.30.1",
        "http-proxy-middleware": "^0.17.4",
        "inline-chunk-manifest-html-webpack-plugin": "^1.1.1",
        "node-sass": "^4.5.3",
        "npm-install-webpack2-plugin": "^5.0.1",
        "open-browser-webpack-plugin": "0.0.5",
        "opn": "^5.1.0",
        "optimize-css-assets-webpack-plugin": "^3.1.1",
        "ora": "^1.3.0",
        "rimraf": "^2.6.1",
        "sass-loader": "^6.0.6",
        "semver": "^5.4.1",
        "shelljs": "^0.7.8",
        "vue-loader": "^13.0.2",
        "vue-style-loader": "^3.0.1",
        "vue-template-compiler": "^2.4.2",
        "webpack": "^3.4.1",
        "webpack-chunk-hash": "^0.4.0",
        "webpack-dev-server": "^2.6.1",
        "webpack-manifest-plugin": "^1.3.1",
        "webpack-merge": "^4.1.0"
    }
}
ratiw commented 6 years ago

The version shown in package.json is not always the current version loaded in your project.

My npm version is 3.10.10, but it was installed by Node v6.11.0

Try

npm -v
npm ls vue

If you're trying out Vuetable, please remove any unnecessary packages first, e.g. electron, and other vue components. Otherwise, it is impossible to know which one(s) is/are causing the problem. Once, you think you know enough then, just add those packages back later.

hanxue commented 6 years ago

I have double-checked all the packages, and I do need all of it. I am developing using a stack of Electron + Vue.js + VueMaterial + Vuetable 2

Can I use a different approach, defining the columns within Vue's <template> , so that I can use properties or computed methods?

Something like:

<template>
  <vuetable ref="vuetable"
        api-url="http://server:port/path/to/api">
        <column name="statusName(shot_version)">
        <column name="author">
    </vuetable>
</template>
<script>
export default {
    methods: {
        statusName(value) {
          return value.toUpperCase()
        },
   }
}
</script>
hanxue commented 6 years ago

@ratiw I got the callback to work by changing from callback: 'statusName' to callback: this.statusName

Could there be an issue with the string parsing for callback?

ratiw commented 6 years ago

Oh, I see. Vuetable is actually looking for the callback method name in the parent instance of Vuetable when you specify it as a string. But if you pass (or define the callback inline) the callback as a function, it will use that function directly.

The former behavior is from the very early version of Vuetable where I still don't quite understand how to pass in the function. It was not removed because I'm afraid that it might break someone's code. I myself usually define the function inline nowadays. Might have to revisit this again.

hanxue commented 6 years ago

Ah, that makes sense now. I appreciate the amount of effort you put in to make vuetable-2 not only extensible and flexible, but also backwards compatible 👍

Maximus1000 commented 6 years ago

Same issue here.

    "vuetable-2": "^1.*.*", // 1.6.0
    "vue": "^2.*.*"
            formatDate (value, fmt) {
                if (value === null ) return ''
                fmt = (typeof fmt === 'undefined') ? 'D MMM YYYY' : fmt
                return moment(value, 'YYYY-MM-DD').format(fmt)
            },

couldn't get formatDate to fire without: callback: this.formatDate right now, I can't figure out how to pass in a fmt argument to the formatDate callback. I've tried a few different methods, can't seem to figure that part out.

For other, Vue, Vuex, Laravel, users, try this.YourCallBackFunction as in

                    {
                        name: 'created_at',
                        title: 'Created',
                        titleClass: 'text-center',
                        dataClass: 'text-center',
                        callback: this.formatDate
                    },
                    {
                        name: 'updated_at',
                        title: 'Updated',
                        titleClass: 'text-center',
                        dataClass: 'text-center',
                        callback: this.formatDate
                    },

Thanks to ratiw for this awesome package!

Georgeek commented 6 years ago

if I move fileds to fieldsFile.js for examle both variant of callback wont work

export default [
  { 
    name: 'status',
    title: 'Status',
    callback: this.statusLabel, 
    // OR 
    callback: 'statusLabel', 
  }
]

in App.vue

statusLabel(value) {
  return value ? 'Active' : 'Archive'
}

When i write fields in App.vue directly it works fine

ratiw commented 6 years ago

@Georgeek You will need to move the statusLabel function into fieldsFile.js as well.

If I'm not wrong, this might be because of the way webpack work. During compilation and bundling, the code in fieldsFile.js is probably in another section, but will eventually get pull into the main code base dynamically.

So, you can do something like this,

function statusLabel(value) {
  return value ? 'Active' : 'Archine'
}

export default [
  { 
    name: 'status',
    title: 'Status',
    callback: statusLabel, 

    // OR declare it inline
    callback: function(value) {
      return value ? 'Active' : 'Archive'
    }, 
  }
]

Please note, however, that in v2.0 of Vuetable-2, the callback option is renamed to formatter and can only accept Function. That means Vuetable will no longer looking for the given function in the parent scope, but instead need you to assign a function to the formatter option.

I was using that approach when I was learning about Vue and that I used the same approach as when I used jQuery. I was waiting to change this for a long time and able to do it in v2.0 of Vuetable-2.

TurboControl commented 5 years ago

Please note, however, that in v2.0 of Vuetable-2, the callback option is renamed to formatter and can only accept Function. That means Vuetable will no longer looking for the given function in the parent scope, but instead need you to assign a function to the formatter option.

It's a little too bad that formatter must be a function. I have to install a formatter for every cell to support search highlight and possible nested data. My field definitions are located on the server and it will support all sorts of data definitions. So when I load the definitions, formatters must be applied in client. If it referenced a method name, then I don't have to get fuzzy on scope. What really hurts is that the only parameters passed are value and the table itself. I lose context of what field it was if I'm trying to do it generically. To get around this, I have to scope anonymous functions with field knowledge instead of having one simple instance. Please pass a 3rd value: the field object itself.

ratiw commented 5 years ago

You should create a Field Component instead, it has all the control you'll need.

piyushdolar commented 4 years ago

Solution: I also was suffering this problem, I also followed this https://github.com/ratiw/vuetable-2-tutorial/wiki/lesson-06 but same situation was occurred to me you just have to do is replace callback to callBack thats it.

example following.

1) Table fields in data:

fields: [ { name: 'nickname', sortField: 'nickname', callBack: 'allcap' }, ]

2) Function in methods:

methods: { allcap: function(value) { return value.toUpperCase(); },

yaswankar commented 4 years ago

Try using the formatter property, Please follow the below syntax

export default [ { name: 'gender', title: 'Gender', formatter(value) { return value === 'M' ? 'Male' : 'Female' }, } ]