GigaTables / reactables

GigaTables is a ReactJS plug-in to help web-developers process table-data in applications and CMS, CRM, ERP or similar systems.
MIT License
144 stars 30 forks source link

data doesn't get updated in GT after editing #106

Closed wangfrombupt closed 6 years ago

wangfrombupt commented 6 years ago

I think the reason lies in line 442-445 of Editor.js, where dataResp doesn't update its values according to the received data. The data in the dababase do get updated.

442 }).then(response => response.json()).then((data) => { 443 editorUpdate(e, dataResp); 444 this.triggerAfter(EditorConstants.EDITOR_EDIT); 445 });

arthurkushman commented 6 years ago

Hi

wangfrombupt commented 6 years ago
  1. only one row is updated;
  2. default sort and no search conditions.
arthurkushman commented 6 years ago

Are u sending back response object from back-end? As it is only possible/reproduced when back-end send empty response or not a json object. with errors like:

Editor.js:555 Uncaught (in promise) SyntaxError: Unexpected end of JSON input
    at eval (Editor.js:555)

You can even send an empty json back and the row will be filled with locally edited values.

wangfrombupt commented 6 years ago

Yes, I send back the updated row from back-end because there is a generated column (just like the case in the row creating) in it. Simply returning an empty json would not make the row filled with newly generated column value.

arthurkushman commented 6 years ago

Could u please post an example of response data here, then I can test with it?

arthurkushman commented 6 years ago

I've tested edit behavior in different situations, weather it is an empty object or an array like this:

{
    "rows": [
        {
            "GT_RowId": 1,
            "id": 1,
            "title": "Test 1021st row sdfvsdfvdf",
            "desc": "<p>vsdfvdsfvsdf<br>\nvsdfvsdf<br>\nvsdfv<\/p>",
            "date": "2018-05-04"
        }
    ]
}

everything works fine, so I'm waiting for your example of output data.

Thomstrong commented 6 years ago

I've tried the following three testing data on release 2.4.3, none of them works:

{"rows":[{"id":482,"gk":"12312","year":2018,"gkhwttl":3213,"metric":1,"GT_RowId":482}]}

{"rows":[{"id":482,"gk":"12312","year":2018,"gkhwttl":3213,"metric":1}]}

{"rows":{"id":482,"gk":"12312","year":2018,"gkhwttl":3213,"metric":1}}

Thomstrong commented 6 years ago

A further debuging of the corresponding code of Editor.js shows that the variable dataResp does contain the updated values, but the content of the GT would not get updated after closing the pop-up window by clicking the "update" button. Only when I click the reload button of the browser, does the content of GT refreshed to show the new value of the edited record.

BTW, I'm a student of wangfrombupt. I like gigatable very much and hope to be helpful for improving it. Looking forward your feedback, thanks.

arthurkushman commented 6 years ago

Ok, I've tried all possible formats from these are perfect fit:

{"rows":[{"id":482,"gk":"12312","year":2018,"gkhwttl":3213,"metric":1,"GT_RowId":482}]}

{"rows":[{"id":482,"gk":"12312","year":2018,"gkhwttl":3213,"metric":1}]}

no errors, warning or not working functionality (by editing rows) found, also tested with multiple rows - works as expected. Suppose there may be problems with GT settings, could u provide settings and editor json here from main.js, it would be better to copy/paste all content from main.js file, or wherever all settings for GT is, with JSX, thus I can debug the issue, what browser are using? version? also will be helpful.

Thomstrong commented 6 years ago

1.about main.js We used the original main.js in the GT source code. Its content is pasted here:

import React from 'react'
import ReactDOM from 'react-dom'
import Reactables from './src/Reactables.jsx'
import Header from './src/components/table/Header.js'
import './main.css'

let editor = {
    ajax: 'http://gigatables.loc/editor.php',
    // it is possible to set discrete urls, http methods for any type of request
    // ajax: {
    //     create: {
    //         url: 'http://gigatables.loc/editor.php',
    //         type: 'POST',
    //         headers: {
    //             'X-Api-Key': '8013b37216a07f50027139d89ee9f822e3784049'
    //         }
    //     },
    //     edit: {
    //         url: 'http://gigatables.loc/editor.php',
    //         type: 'PUT',
    //         headers: {
    //             'X-Api-Key': '8013b37216a07f50027139d89ee9f822e3784049',
    //             'X-Header-Key': 'foo-bar'
    //         }
    //     },
    //     delete: {
    //         url: 'http://gigatables.loc/editor.php',
    //         type: 'DELETE',
    //         headers: {
    //             'X-Api-Key': '8013b37216a07f50027139d89ee9f822e3784049',
    //             'X-Header-Key': 'foo-bar-baz'
    //         }
    //     }
    // },
    ajaxFiles: 'http://gigatables.loc/uploadFiles.php',
    struct: {
        buttons: [ 'top', 'bottom' ] // buttons
    },
    fields: [
        {
            label: 'ID',
            name: 'id',
            type: 'hidden'
        },
        {// an example of using select - automatically selected if matches with data in table column
            label: 'Types:',
            name: 'types[]',
            values: [// if select,checkbox,radio etc types - need this pre-set structure of values
                { 'key1': 'val1' },
                { 'key2': 'val2' }
            ],
            type: 'select' // select,checkbox,radio
//              attrs: [
//                {'multiple':true}
//              ]
        },
        {
            label: 'Article title:',
            name: 'title',
            type: 'text', // default, other: password, file, select, multiselect etc
            fieldsetOpen: true,
            legend: 'Required fields',
            attrs: [
                { 'pattern': '^[A-Za-z0-9_]+$' },
                { 'className': 'titleField' }
            ]
        },
        {
            label: 'Description:',
            name: 'desc',
            type: 'textarea',
            plugins: 'rte',
            attrs: [
                { 'className': 'descriptionField' }
            ],
            fieldsetClose: true
        },
        {
            label: 'Date Time:',
            name: 'date',
            type: 'date'
        },
        {
            label: 'Image:',
            name: 'image',
            type: 'file'
        }
    ]
}

let settings = {
    struct: {
        search: [ 'top', 'bottom' ],
        rowsSelector: [ 'desc', 'top', 'bottom' ],
        pagination: [ 'bottom' ],
        fixedHeader: false, // default false
        editableCells: true, // default false
        aggregateFooter: true, // default false
        download: {
            csv: false
        },
        width: '950px'
    },
    lang: 'en', // english default
    perPageRows: [ 25, 50, 100, 200 ],
    defaultPerPage: 50,
    headers: {
        'X-Api-Key': '8013b37216a07f50027139d89ee9f822e3784049',
        'X-Header-Key': 'foo-bar'
    },
    ajax: 'http://gigatables.loc/gigatables.php',
    // ajax: new Promise((resolve) => {
    //     resolve('http://gigatables.loc/gigatables.php')
    // }),
    // ajaxAutoloadData: true, // default false
    // ajaxAutoloadPeriod: 8, // sec
    requestType: 'GET',
    columns: [
        {// include all defaults
            data: 'id',
            sortable: true, // true by defualt
            visible: true, // true by defualt
            searchable: true, // true by defualt
            discreteSearch: true, // false by default
            discreteSearchValue: function (title) {
                return 'Search by field - ' + title
            }
        },
        {
            data: 'title',
            cISearch: true, // default false
            footer: 'frequency'
        },
        {
            data: 'desc',
            sortable: false,
            discreteSearch: true,
            discreteCISearch: true // default false
        },
        {
            data: 'date',
            searchable: false
        },
        {
            data: 'info'
        },
        {
            data: 'field1',
            plugins: 'progressbar'
        },
        {
            data: 'field2',
            footer: 'avg'
        },
        { data: 'field3', visible: false }
    ],
    columnOpts: [
        {
            render: (data, row, type) => (
                <div>
                    <form method="post" action="">
                        <input type="hidden" name="action" value="forms"/>
                        <input type="hidden" name="id" value={row.id}/>
                        <div>{data}</div>
                    </form>
                </div>),
            target: 'title' // provide data column index to match opts
        },
        {
            render: (data, row, type) => (
                <div>
                    <div>{data}</div>
                    <div>{(row.id % 2 === 0) ? '**' : '*'}</div>
                </div>
            ),
            target: 'date'
        }
    ],
    tableOpts: {
        buttons: [
            // {
            //     extended: 'editor_reload',
            //     editor: editor
            // },
            // {// to set CSV Download button
            //     extended: "editor_csv",
            //     editor: editor,
            // },
            {
                extended: 'editor_create', editor: editor, triggerAfter: (function () {
                    console.log('after create')
                }), triggerBefore: (function () {
                    console.log('before create')
                })
            },
            {
                extended: 'editor_edit', editor: editor, triggerBefore: (function () {
                    console.log('before edit')
                })
            },
            {
                extended: 'editor_remove', editor: editor, triggerAfter: (function () {
                    console.log('after del')
                })
            }
        ],
        buttonsPosition: [ 'top', 'bottom' ],
        theme: 'std'
    }
}

ReactDOM.render(
    <Reactables editor={editor} settings={settings}>
        <Header data="id">ID</Header>
        <Header data="title">Name</Header>
        <Header data="desc">Description</Header>
        <Header data="date">Date</Header>
        <Header data="info">Info</Header>
        <Header data="field2">Field123 but data from field2</Header>
        <Header data="field1">Field1</Header>
        <Header data="field3">Field3 invisible</Header>
        <Header>Field3 invisible</Header>
    </Reactables>,
    document.getElementById('app'))
Thomstrong commented 6 years ago
  1. about GT setting and Editor jaon The following code is the file that uses GT.
    
    import React from 'react';
    //import 'react-bootstrap-table-next/dist/react-bootstrap-table2.min.css';
    import { Reactables, Header } from 'gigatables-react'
    import 'gigatables-react/main.css';
    //the following imports are used for debugging gigatable
    //import Reactables from 'gigatables-react/src/Reactables.jsx'
    //import Header from 'gigatables-react/src/components/table/Header.js'

let editor = { ajax: { create: { url: '/hwttl', type: 'POST', }, edit: { url: '/hwttl', type: 'PUT', }, delete: { url: '/hwttl', type: 'DELETE', }, }, //ajaxFiles: 'http://gigatables.loc/uploadFiles.php', struct: { buttons: ['top', 'bottom'] // buttons }, fields: [ { label: "年:", name: "year", type: 'text', }, { label: "港口:", name: "gk", type: 'text' }, { label: "港口货物吞吐量:", name: "gkhwttl", type: 'text', }, ] };

let settings = { struct: { search: ['top', 'bottom'], rowsSelector: ['asc', 'top', 'bottom'], pagination: ['top', 'bottom'], fixedHeader: false, // default false editableCells: false, // default false }, lang: 'ch', // english default perPageRows: [25, 50, 100, 200, 500], defaultPerPage: 50, ajax: '/get_table_hwttl', requestType: 'GET', columns: [ { data: "year", sortable: true, searchable: true }, { data: "gk", sortable: true, searchable: true }, { data: "gkhwttl", sortable: true, searchable: true }, { data: "metric", sortable: true, searchable: true }, ], columnOpts: [ { render: function (data, row, type) { return '

' + data + '
'; }, target: 2 }, { render: function (data, row, type) { return '
' + data + '
'; }, target: 3 } ], tableOpts: { buttons: [ {extended: "editor_create", editor: editor, triggerAfter: (function () { //console.log('after create'); }), triggerBefore: (function () { //console.log('before create'); })}, {extended: "editor_edit", editor: editor}, {extended: "editor_remove", editor: editor, triggerAfter: (function () { //console.log('after del'); })} ], buttonsPosition: ['top', 'bottom'], theme: 'std' } };

class HwttlTable extends React.Component {

render() { return (

港口
港口货物吞吐量(万吨)
指标值
);

} }

export default HwttlTable;

Thomstrong commented 6 years ago
  1. about browser We use Chrome 66.0.3359.139 (64bit)on Windows 10 (64bit) to carry out the test.
Thomstrong commented 6 years ago

I have a new finding! I try to modify the variable "editeableCells" of GT setting to "true", and the record will change after update button clicked.But when I click the field I have changed just now, the value will be go back to the old one right away

arthurkushman commented 6 years ago

Thx a lot, as soon as I find time - try to fix this.

arthurkushman commented 6 years ago

Fixed by adding children prop check to Column component, this was serious glitch which could produce unexpected behavior. Patch release - https://github.com/GigaTables/reactables/releases/tag/2.4.4

Editable cells also fixed, if you send back an object like:

{
    "rows": [
        {
            "desc": "Foo bar baz",
            "id": 968
        }
    ]
}

cell will be properly edited. Thx.

Thomstrong commented 6 years ago

Now the content of GT can reflect the new values of editor fields, but the generated column value is not updated. It is the same issue as #98. Please fix it as well.

arthurkushman commented 6 years ago

Thank u - I've opened issue #108 for better history and closing this.