Author Topic: save data when batch-copy for select column and pivot grid  (Read 198 times)

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
save data when batch-copy for select column and pivot grid
« on: November 07, 2024, 12:35:14 pm »
When batch-copying data into select(dropdown) column, the new updated data of select(dropdown) column could not be saved to server.
But if use mouse to click the select element one by one to change the data, the changes can be saved to server.
Maybe there's something wrong for pqgrid.
Would you like to provide a sample for saving select batch-copying data?
When set the width of first column(in https://paramquery.com/pro/demos/pivot) to 500px, after press "edit and run", the width of first column keep unchanged(still 158px).


        var colM = [
            //extra column to show grouping (for both pivot and row grouping mode, used along with groupModel.titleIndx )           
            {
                title: 'Group', tpHide: true, menuInHide: true,
                dataIndx: 'grp',
           width:500,//width is changed here , but no expected result.
                menuUI: {
                    tabs: ['hideCols'] //display only hide columns tab in menu.
                }
            },
« Last Edit: November 07, 2024, 01:20:45 pm by paramvir »

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #1 on: November 11, 2024, 07:36:17 am »
Dear Paramvir,
Batch-copy for select column could not be saved, this is really a trouble, end-user maybe be unware of the problem and make wrong operation.
Would you like to provide any advice or treat it as a bug?
Pivotable's style control is also a trouble for end-user.
« Last Edit: November 11, 2024, 08:05:14 am by hyh888 »

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column
« Reply #2 on: November 16, 2024, 04:42:05 pm »
Dear Paramvir,
If there is no solution for saving-data of batch-copy of select column, I have to remove the select of pqgrid.
This is really a trouble for me.

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #3 on: November 19, 2024, 07:38:57 pm »
Batch editing is based on grid getChanges method.

getChanges include the updates due to copy paste in select lists similar to inline editing of individual editing of select lists.

So I don't see any issue there unless you share some technical details.

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #4 on: November 20, 2024, 11:10:13 am »
Dear Paramvir,
I changed code of demo in https://paramquery.com/pro/demos/editing_custom , you can copy all code to your demo and press "edit and run".
Firstly batch-copy many "USA"(this should be pre-copied in excel) to first row, secondly press "get change", then you will find than updatelist has no content in the console.
I put screencopy in the attach.

Here is the changed code:
$(function () { 
function saveChanges() { 
var grid = this; 
//attempt to save editing cell. 
if (grid.saveEditCell() === false) { 
return false; 
}


        if (grid.isDirty() && grid.isValidChange({ focusInvalid: true }).valid) {

            var gridChanges = grid.getChanges({ format: 'byVal' });

            //post changes to server
            $.ajax({
                dataType: "json",
                type: "POST",
                async: true,
                beforeSend: function (jqXHR, settings) {
                    grid.showLoading();
                },
                url: "/pro/products/batch", //for ASP.NET, java   
                //url: '/products.php?pq_batch=1', for PHP                                           
                data: {
                    //JSON.stringify not required for PHP
                    list: JSON.stringify(gridChanges)
                },
                success: function (changes) {
                    //debugger;
                    grid.commit({ type: 'add', rows: changes.addList });
                    grid.commit({ type: 'update', rows: changes.updateList });
                    grid.commit({ type: 'delete', rows: changes.deleteList });

                    grid.history({ method: 'reset' });
                },
                complete: function () {
                    grid.hideLoading();
                }
            });
        }
    }

    //rename the bootstrap datepicker to avoid conflict with jquery date picker.
    if (typeof $.fn.datepicker.noConflict == "function") {
        $.fn.bootstrapDatepicker = $.fn.datepicker.noConflict();
    }

    var books = [
        "ActionScript",
        "AppleScript",
        "Asp",
        "BASIC",
        "C",
        "C++",
        "Clojure",
        "COBOL",
        "ColdFusion",
        "Erlang",
        "Fortran",
        "Groovy",
        "Haskell",
        "Java",
        "JavaScript",
        "Lisp",
        "Perl",
        "PHP",
        "Python",
        "Ruby",
        "Scala",
        "Scheme"
    ];
    function autoCompleteEditor(source) {
        return function (ui) {
            ui.$cell.addClass('ui-front');//so that dropdown remains with input.

            //initialize the editor
            ui.$editor.autocomplete({
                //appendTo: ui.$cell, //for grid in maximized state.
                source: source,
                position: {
                    collision: 'flipfit',
                    within: ui.$editor.closest(".pq-grid")
                },
                selectItem: { on: true }, //custom option
                highlightText: { on: true }, //custom option
                minLength: 0
            }).one('focus', function () {
                //open the autocomplete upon focus
                $(this).autocomplete("search", "");
            });
        }
    }
    function dateEditor(ui) {

        //initialize the editor
        ui.$cell.find("input")
            .attr('readonly', 'readonly')
            .datepicker({
                changeMonth: true,
                changeYear: true,
                //convert from excel to jquery ui format
                dateFormat: pq.excelToJui(ui.column.format),
                showAnim: '',
                onSelect: function () {
                    this.firstOpen = true;
                },
                beforeShow: function (input, inst) {
                    setTimeout(function () {
                        //to fix the issue of datepicker z-index when grid is in maximized state.
                        $('.ui-datepicker').css('z-index', 999999999999);
                    });
                    //return !this.firstOpen; uncomment if don't want to allow datepicker editor to open upon focus in editor after first opening.
                },
                onClose: function () {
                    this.focus();
                }
            });
    }

    function bootstrapDateEditor(ui) {
        //initialize the editor
        ui.$cell.find("input")
            .bootstrapDatepicker({
                format: ui.column.format,
            })
            .on('changeDate', function (e) {
                $(this).focus();
                $(this).bootstrapDatepicker('hide');
            })

    }

    var colM = [
        {
            title: "Ship Country", dataIndx: "ShipCountry", width: 120,
            cls: 'pq-drop-icon pq-side-icon',
            editor: {
                type: "textbox",
                attr: "autocomplete='off'",
                init: autoCompleteEditor("/pro/demos/getCountries")
            },
            validations: [
                { type: 'minLen', value: 1, msg: "Required" },
                {
                    type: function (ui) {
                        var value = ui.value,
                            _found = false;
                        //remote validation
                        //debugger;
                        $.ajax({
                            url: "/pro/demos/checkCountry",
                            data: { 'country': value },
                            async: false,
                            success: function (response) {
                                if (response == "true") {
                                    _found = true;
                                }
                            }
                        });
                        if (!_found) {
                            ui.msg = value + " not found in list";
                            return false;
                        }
                    }
                }
            ]
        },
        {
            title: "Books", dataIndx: "books", width: 90,
            cls: 'pq-drop-icon pq-side-icon',
            editor: {
                type: "textbox",
                attr: "autocomplete='off'",
                init: autoCompleteEditor(books)
            },
            validations: [
                { type: 'minLen', value: 1, msg: "Required" },
                {
                    type: function (ui) {
                        var value = ui.value;
                        if (books.indexOf(value) == -1) {
                            ui.msg = value + " not found in list";
                            return false;
                        }
                    }, icon: 'ui-icon-info'
                }
            ]
        },
        {
            title: "Fruits", dataIndx: "fruits", width: 140,
            //custom editor.
            editor: {
                options: ['Apple', 'Orange', 'Kiwi', 'Guava', 'Grapes'],
                type: 'div',
                init: function (ui) {
                    //debugger;
                    var options = ui.column.editor.options,
                        str = options.map(function (option) {
                            var checked = (option == ui.cellData) ? 'checked = checked' : '';
                            return "<input type='radio' " + checked + " name='" + ui.dataIndx + "' style='margin-left:5px;' value='" + option + "'>  " + option;
                        }).join("");

                    //ui.$cell.append("<div class='pq-editor-focus' tabindex='0' style='padding:5px;margin-top:1px;'>" + str + "</div>");
                    ui.$cell.children('div').css({ padding: '5px' }).html(str);
                },
                getData: function (ui) {
                    return ui.$cell.find('input:checked').val();
                }
            }
        },
        {
            title: "Order ID", width: 100, dataIndx: "OrderID",
            editor: {
                type: "textbox",
                //make it html5 number editor.
                attr: "type='number'"
            }
        },
        {
            title: "Date jui",
            width: "120",
            dataIndx: "OrderDate",
            dataType: 'date',
            format: 'dd-mm-yyyy', //display format.
            fmtDateEdit: 'dd-mm-yyyy', //format of date value in editor
            cls: 'pq-calendar pq-side-icon',
            editor: {
                type: 'textbox',
                init: dateEditor
            },
            validations: [
                { type: 'regexp', value: '^[0-9]{4}-[0-9]{2}-[0-9]{2}$', msg: 'Not in yyyy-mm-dd format' }
            ]
        },
        {
            title: "Date bootstrap",
            width: "120",
            dataIndx: "OrderDate2",
            dataType: 'date',
            format: 'yyyy-mm-dd', //display format.
            fmtDateEdit: 'yyyy-mm-dd', //format of date value in editor
            cls: 'pq-calendar pq-side-icon',
            editor: {
                type: 'textbox',
                init: bootstrapDateEditor,
                preventClose: function (ui) {
                    return $(".datepicker-dropdown").is(":visible");
                }
            },
            validations: [
                { type: 'regexp', value: '^[0-9]{4}-[0-9]{2}-[0-9]{2}$', msg: 'Not in yyyy-mm-dd format' }
            ]
        },
        //column with pqselect editor
        {
            title: "Shipping Via", dataIndx: "ShipVia", width: 110,
            cls: 'pq-drop-icon pq-side-icon',
            editor: {
                type: 'select',
                options: [
                    { "SE": "Speedy Express" },
                    { "UP": "United Package" },
                    { "FS": "Federal Shipping" }
                ],
                init: function (ui) {
                    ui.$cell.find("select").pqSelect();
                    setTimeout(function () {
                        ui.$cell.find("select").pqSelect('open');
                    })
                }
            },
            //render required to display options text corresponding to value stored in the cell.
            render: function (ui) {
                var option = ui.column.editor.options.find(option => option[ui.cellData] != null);
                return option ? option[ui.cellData] : "";
            },
            validations: [
                { type: 'minLen', value: 1, msg: "Required" },
                {
                    type: function (ui) {
                        var value = ui.value,
                            option = ui.column.editor.options.find(option => option[value] != null);
                        if (!option) {
                            ui.msg = value + " not found in list";
                            return false;
                        }
                    }, icon: 'ui-icon-info'
                }
            ]
        },
        {
            title: "Shipping Via2", dataIndx: "ShipVia2", width: 110,
            cls: 'pq-drop-icon pq-side-icon',
            editor: {
                type: 'select',
                valueIndx: "value",
                labelIndx: "text",
                options: [
                    { value: "", text: "" },
                    { value: "SE", text: "Speedy Express" },
                    { value: "UP", text: "United Package" },
                    { value: "FS", text: "Federal Shipping" }
                ]
            },
            //render required to display options text corresponding to value stored in the cell.
            render: function (ui) {
                var option = ui.column.editor.options.find(option => option.value == ui.cellData );                   
                return option ? option.text : "";
            },
            validations: [
                { type: 'minLen', value: 1, msg: "Required" },
                {
                    type: function (ui) {
                        var value = ui.value,
                            option = ui.column.editor.options.find(option => option.value == value );
                        if (!option) {
                            ui.msg = value + " not found in list";
                            return false;
                        }
                    }, icon: 'ui-icon-info'
                }
            ]
        },
        {
            title: "Shipping Address", width: 200, dataIndx: "ShipAddress",
            editor: {
                style: {
                    width: "auto"
                }
            },
            editModel: {
                saveKey: '' //disable or set it to some other key code to free up use of Enter key for line breaks.
            },
            validations: [{ type: 'minLen', value: 1, msg: "Required" }]
        },
        {
            title: "Freight", dataIndx: "Freight", dataType: "float", width: 100, format: '$#,###.00',
            editor: { select: true },
            validations: [{ type: 'gte', value: 1, msg: "should be >= 1" }],
            editModel: { keyUpDown: true }
        }
    ];
    var dataModel = {
        location: "remote",
        dataType: "JSON",
        method: "GET",
        url: "/content/invoice.json",
        getData: function (response) {
            response.data.forEach(function (rd) {
                //convert dates from 'mm/dd/yyyy' to ISO format.
                rd.OrderDate = pq.parseDate(rd.OrderDate, 'mm/dd/yyyy');

                //make ShipAddress multiline text.
                rd.ShipAddress = rd.ShipAddress + "\n" + rd.ShipCity + "\n" + (rd.ShipRegion || "") + "\n" + rd.ShipPostalCode;
            })
            return response;
        }
    }

    //finally define the grid.
    $("div#grid_custom_editing").pqGrid({
                  toolbar: {
            items: [
                {
                    type: 'button', icon: 'ui-icon-plus', label: 'New Product', listener: function () {
                        //append empty row at the end.                           
                        var rowData = { ProductID: 34, UnitPrice: 0.2 }; //empty row
                        var rowIndx = this.addRow({ rowData: rowData, checkEditable: true });
                        this.goToPage({ rowIndx: rowIndx });
                        this.editFirstCellInRow({ rowIndx: rowIndx });
                    }
                },
                { type: 'separator' },
                {
                    type: 'button', icon: 'ui-icon-disk', label: 'Save Changes', cls: 'changes', listener: saveChanges,
                    options: { disabled: true }
                },
                {
                    type: 'button', icon: 'ui-icon-cancel', label: 'Reject Changes', cls: 'changes', listener: function () {
                        this.rollback();
                        this.history({ method: 'resetUndo' });
                    },
                    options: { disabled: true }
                },
                {
                    type: 'button', icon: 'ui-icon-cart', label: 'Get Changes', cls: 'changes', listener: function () {
                        var changes = this.getChanges({ format: 'byVal' });
                        if (console && console.log) {
                            console.log(changes);
                        }
                        alert("Please see the log of changes in your browser console.");
                    },
                    options: { disabled: true }
                },
                { type: 'separator' },
                {
                    type: 'button', icon: 'ui-icon-arrowreturn-1-s', label: 'Undo', cls: 'changes', listener: function () {
                        this.history({ method: 'undo' });
                    },
                    options: { disabled: true }
                },
                {
                    type: 'button', icon: 'ui-icon-arrowrefresh-1-s', label: 'Redo', listener: function () {
                        this.history({ method: 'redo' });
                    },
                    options: { disabled: true }
                }
            ]
        },
                  trackModel: { on: true }, //to turn on the track changes.   
        history: function (evt, ui) {
            var $tb = this.toolbar();
            if (ui.canUndo != null) {
                $("button.changes", $tb).button("option", { disabled: !ui.canUndo });
            }
            if (ui.canRedo != null) {
                $("button:contains('Redo')", $tb).button("option", "disabled", !ui.canRedo);
            }
            $("button:contains('Undo')", $tb).button("option", { label: 'Undo (' + ui.num_undo + ')' });
            $("button:contains('Redo')", $tb).button("option", { label: 'Redo (' + ui.num_redo + ')' });
        },
        title: "Shipping Orders <b>(Custom editing)</b>",
        dataModel: dataModel,
        colModel: colM,
        //we don't want to allow invalid values while paste of data.
        pasteModel: {allowInvalid: false},
        //scrollModel: { autoFit: true },
        columnTemplate: {
            valign: 'center',
            width: 150
        },
        create: function (evt, ui) {
            this.widget().pqTooltip();
        },
        editModel: {
            //clicksToEdit: 1,
            keyUpDown: false,
            onBlur: 'save'
        },
        numberCell: { show: false },
        resizable: true
    });
});

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #5 on: November 21, 2024, 11:23:04 am »
With your code, getChanges returns empty updateList even for inline editing of any cell.

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #6 on: November 21, 2024, 06:42:13 pm »
Dear Paramvir,
I also found that there were problem in the code, would you like to correct the code in this code block?  or provide a another demo?
Million thanks, this problem has troubled me for a long time.

The "get changes" button changed from disable status to enable status, but I don'nt know why getChanges returns empty updateList after batch-copying to select column(the first column).
« Last Edit: November 21, 2024, 06:55:32 pm by hyh888 »

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #7 on: November 22, 2024, 07:07:49 pm »
Dear Team,
To persuade you that this is a bug, you can batch-copy many "United Package"s (this should be prepared in excel) into the 3rd col in https://paramquery.com/demos/edit_select.
Then you will find that the second col is blank, if you use mouse to select "United Package" one by one in 3rd col, "UP" will show in second col.


paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #8 on: November 22, 2024, 09:08:03 pm »
Please check this example: https://paramquery.com/pro/demos/datamap

hyh888

  • Pro Enterprise
  • Full Member
  • *
  • Posts: 142
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #9 on: Today at 03:43:22 am »
Dear Team,
In https://paramquery.com/pro/demos/datamap, the select col's(the 1st col's) valueIndx and labelIndx are same(in my case they are different), maybe the formula will force the 1st col to be updated when batch-copying.

https://paramquery.com/pro/demos/datamap and  https://paramquery.com/demos/edit_select are not same topic.

I wonder why batch-copy could not work well in https://paramquery.com/demos/edit_select, and how to make it work.
It's obviously that if there no extra code to fix bug or add configuration, the select in https://paramquery.com/demos/edit_select could not handle batch-copy smoothly.
« Last Edit: Today at 03:57:34 am by hyh888 »

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6310
    • View Profile
Re: save data when batch-copy for select column and pivot grid
« Reply #10 on: Today at 10:45:01 am »
ShipVia (2nd column) in this example: https://paramquery.com/pro/demos/edit_select has different valueIndx, labelIndx and it works with copy paste.

editor.mapIndices is not designed for copy paste.

Please use formulas instead of editor.mapIndices in case there are any dependencies between different columns.