Author Topic: How can i use Autofill feature with Autosave?  (Read 4650 times)

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
How can i use Autofill feature with Autosave?
« on: May 16, 2018, 02:28:05 pm »

Posts: 1
View Profile

How can i use Autofill feature with Autosave?
« on: May 15, 2018, 07:29:09 pm »
Quote
Hi Experts,

I am using PQ Grid Pro latest version and stuck in a issue from last two days.

Actually what i am trying to do is to use autofill feature with auto save.

Auto save feature is working correctly and i am using batch editing. So separate list for add,update and delete are going to server when auto save runs.

I tried to add extra blank rows in data model, I've added blank rows at server so in response i got blank rows.

But issue is that when i edit a cell and enter value, grid is not marking that cell dirty. So there is no red mark on cell on top right corner.

I am checking isDirty() at the time of auto save.

As grid is not marking my changes as dirty, so these values are not going to database.

Can you guys please suggest me what should i do or what i am doing wrong?

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6309
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #1 on: May 16, 2018, 02:40:56 pm »
Row is considered new row by grid unless primary key is generated for the row.

Autofill can be used on new rows as well as existing rows ( having primary key ).

New rows are send to server in addList
and existing rows are send to server in updateList.

So what's the issue?

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #2 on: May 16, 2018, 03:25:29 pm »
Issue is that when i edit any cell and after my editing completes, grid does not mark that cell dirty.

Thus autosave do not call server URL to save data.

Here is my code:
-------------------------


var $grid = jQuery("#grid_json");
jQuery(document).ready(function(){

    var gridheight = 700;
   
    var pqVS = {
        rpp: 100, //records per page.
        init: function () {
            this.totalRecords = 0;
            this.requestPage = 1; //begins from 1.
            this.data = [];
        }
    };
    pqVS.init();
   
    //define common ajax object for addition, update and delete.
    var ajaxObj = {
        dataType: "JSON",
        beforeSend: function () {
            this.showLoading();
        },
        complete: function () {
            this.hideLoading();
        },
        error: function () {
            this.rollback();
        }
    };
   
    //called by delete button.
    function deleteRow(rowIndx, grid) {
        var ans = window.confirm("Are you sure want to delete?");
        if (ans) {
            var ProductID = grid.getRecId({ rowIndx: rowIndx });
            grid.deleteRow({ rowIndx: rowIndx });
        }
    }
   
   
    /**** AUTO SAVE code starts here ***/
    var interval;
   
    function saveChanges() {
        /**
        1. if there is no active ajax request.
        2. there is no ongoing editing in the grid.
        3. grid is dirty.
        4. all changes are valid.
        */
        if (!$.active && !$grid.pqGrid('getEditCell').$cell && $grid.pqGrid('isDirty') && $grid.pqGrid('isValidChange',{ allowInvalid: true }).valid) {
           
            var gridChanges = $grid.pqGrid('getChanges', { format: 'byVal' });
            $.ajax($.extend({}, ajaxObj, {
                url: "http://local.project/product",
                data: {
                    cat_id: 3,
                    list: JSON.stringify( gridChanges )
                },
                dataType: "json",
                type: "POST",
                async: true,
                beforeSend: function (jqXHR, settings) {
                    $grid.pqGrid( "option", "strLoading", "Saving.." );
                    $grid.pqGrid( "showLoading" );
                },
                success: function (changes) {
                    //commit the changes.
                    $grid.pqGrid("commit", { type: 'add', rows: changes.addList });
                    $grid.pqGrid("commit", { type: 'update', rows: changes.updateList });
                    $grid.pqGrid("commit", { type: 'delete', rows: changes.deleteList });
                },
                complete: function () {
                    $grid.pqGrid( "hideLoading" );
                    $grid.pqGrid( "option", "strLoading", $.paramquery.pqGrid.defaults.strLoading );
                }
            }));
        }
    }
    //save changes from a timer.
    interval = setInterval(saveChanges, 2000);
    /**** AUTO SAVE code ends here ***/
   
    var obj = {
        hwrap: false,
        rowBorders: false,
        autoRow: false,
        rowHt: 35,
        trackModel: { on: true }, //to turn on the track changes.
        toolbar: {
            items: [{
                type: 'button',
                icon: 'ui-icon-plus',
                label: 'New Product',
                listener: function () {
                    //append empty row at the end.
                    var rowData = {
                        catAttr_11: "",
                        catAttr_13: ""
                    }; //empty row template
                    var rowIndx = $grid.pqGrid('addRow', { rowData: rowData });
                    $grid.pqGrid('goToPage', { rowIndx: rowIndx });
                    $grid.pqGrid('editFirstCellInRow', { rowIndx: rowIndx });
                }
            },
            { type: 'separator' },
            {
                type: 'button',
                icon: 'ui-icon-arrowreturn-1-s',
                label: 'Undo',
                cls: 'changes',
                options: { disabled: true },
                listener: {
                    "click": function (evt, ui) {
                        $grid.pqGrid("history", { method: 'undo' });
                    }
                }
            },
            {
                type: 'button',
                icon: 'ui-icon-arrowrefresh-1-s',
                label: 'Redo',
                options: { disabled: true },
                listener: {
                    "click": function (evt, ui) {
                        $grid.pqGrid("history", { method: 'redo' });
                    }
                }
            }]
        },
        scrollModel: {  autoFit: true },
        editor: { select: true },
        title: "<b>List Of Products</b>",
        change: function (evt, ui) {
            //console.log(ui);
            //saveChanges can also be called from change event.
        },
        destroy: function () {
            //clear the interval upon destroy.
            clearInterval(interval);
        },
        history: function (evt, ui) {
            var $grid = this.widget();
            if (ui.canUndo != null) {
                $("button.changes", $grid).button("option", { disabled: !ui.canUndo });
            }
            if (ui.canRedo != null) {
                $("button:contains('Redo')", $grid).button("option", "disabled", !ui.canRedo);
            }
            $("button:contains('Undo')", $grid).button("option", { label: 'Undo (' + ui.num_undo + ')' });
            $("button:contains('Redo')", $grid).button("option", { label: 'Redo (' + ui.num_redo + ')' });
        },
        postRenderInterval: -1, //synchronous post render.
        swipeModel: { on: false },
        selectionModel: { type: 'cell' },
        filterModel: { on: true, header: true, type: 'remote' },
        resizable: true,
        flex:{one: true},
        virtualX: true,
        virtualY: true,
        load: function (evt, ui) {
            var grid = this,
            data = grid.option('dataModel').data;
            grid.widget().pqTooltip(); //attach a tooltip.
           
            //validate the whole data.
            grid.isValid({ data: data });
        },
        pageModel: { type: "local", rPP: 100 , rPPOptions: [100,200,300,400,500]},
        editable: true,
        create: function (evt, ui) {
            this.widget().pqTooltip();
        },
        beforeTableView: function (evt, ui) {
            var initV = ui.initV,
            finalV = ui.finalV,
            data = pqVS.data,
            rpp = pqVS.rpp,
            requestPage;
           
            if (initV != null) {
               
                //if records to be displayed in viewport are not present in local cache,
                //then fetch them from remote database/server.
               
                if (data[initV] && data[initV].pq_empty) {
                    requestPage = Math.floor(initV / rpp) + 1;
                }
                else if (data[finalV] && data[finalV].pq_empty) {
                    requestPage = Math.floor(finalV / rpp) + 1;
                }
               
                if (requestPage >= 1) {
                    if (pqVS.requestPage != requestPage) {
                       
                        pqVS.requestPage = requestPage;
                       
                        //initiate remote request.
                        this.refreshDataAndView();
                    }
                }
            }
        }
    };
   
    obj.dataModel = {
        dataType: "JSON",
        location: "remote",
        recIndx: "ProductID",
        url: "http://local.project/product/getproducts/?cat_id=3",
        postData: function () {
            return {
                pq_curpage: pqVS.requestPage,
                pq_rpp: pqVS.rpp
            };
        },
        getData: function (response) {
            var data = response.data,
            totalRecords = response.totalRecords,
            len = data.length,
            curPage = response.curPage,
            pq_data = pqVS.data,
            init = (curPage - 1) * pqVS.rpp;
            if (!pqVS.totalRecords) {
                //first time initialize the rows.
                for (var i = len; i < totalRecords; i++) {
                    pq_data[i + init] = { pq_empty: true };
                }
                pqVS.totalRecords = totalRecords;
            }
            for (var i = 0; i < len; i++) {
                pq_data[i + init] = data;
                pq_data[i + init].pq_empty = false;
            }
            return { data: pq_data }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            console.log(errorThrown);
        }
    };
   
    obj.colModel = [
        {
            "title": "Product ID",
            "width": "165",
            "dataIndx": "ProductID",
            "dataType": "integer",
            "editable": false
        }
        ,{
            "title": "Demo Field",
            "width": "165",
            "dataIndx": "catAttr_11",
            "filter": {
                "type": "textbox",
                "condition": "begin",
                "listeners": ["change"]
            },
            "editor": {
                "type": "textbox"
            }
        }
        ,{
            "title": "Demo Field 2",
            "width": "165",
            "dataIndx": "catAttr_13",
            "filter": {
                "type": "textbox",
                "condition": "begin",
                "listeners": ["change"]
            },
            "editor": {
                "type": "textbox"
            }
            ,"validations": [
               
                { type: 'minLen', value: 1, msg: "Required" }
            ]
        }
        ,{ title: "", editable: false, minWidth: 165, sortable: false,
        render: function (ui) {
            return "<button type='button' class='delete_btn'>Delete</button>";
        },
        postRender: function (ui) {
            var rowIndx = ui.rowIndx,
            grid = this,
            $cell = grid.getCell(ui);
           
            //delete button
            $cell.find(".delete_btn").button({ icons: { primary: 'ui-icon-close'} })
            .bind("click", function (evt) {
                deleteRow(rowIndx, grid);
            });
        }
    }
];

$grid.pqGrid(obj);
$grid.pqGrid( "option", "height", gridheight );

//check the changes in grid before navigating to another page or refresh data.
$grid.pqGrid("pager").on("beforeChange beforeRefresh", function (evt, ui) {
    if ($grid.pqGrid( "isDirty")) {
        var ans = window.confirm("There are unsaved changes. Are you sure?");
        if (!ans) {
            return false;
        }
    }
});
});

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #3 on: May 16, 2018, 03:28:00 pm »
Also to add blank rows, here is my JSON response from server side:


{
   "totalRecords": 1,
   "curPage": 1,
   "data": [{
      "ProductID": 38,
      "catAttr_11": "test",
      "catAttr_13": "test"
   }, {
      "catAttr_11": "",
      "catAttr_13": ""
   }, {
      "catAttr_11": "",
      "catAttr_13": ""
   }, {
      "catAttr_11": "",
      "catAttr_13": ""
   }, {
      "catAttr_11": "",
      "catAttr_13": ""
   }, {
      "catAttr_11": "",
      "catAttr_13": ""
   }]
}

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6309
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #4 on: May 16, 2018, 04:17:19 pm »
As mentioned earlier,

1 rows without primary key are considered new rows ( addList )

2. Cells are marked dirty in case of existing rows only. ( updateList )

When there are blank rows, they are not sent to server ( addList ) as long as all required fields ( e.g catAttr_13 ) are filled up.

Also blank rows should be added in grid with addRow method and not by JSON response from server side.
« Last Edit: May 16, 2018, 04:22:53 pm by paramquery »

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #5 on: May 16, 2018, 04:32:31 pm »
Hi,

Thanks for looking into this issue and explain what is happening here.

But I saw your autofill example, there is a code to add 100 blank rows:

//add some empty rows.
 for(var i=0; i< 100; i++){
      data.push({});
 }

Should i use this type of code to add blank rows?

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #6 on: May 16, 2018, 05:07:53 pm »
Hi,

I applied below code as you said that blank rows should not come in server response. So i put code in data model as below:

obj.dataModel = {
    dataType: "JSON",
    location: "remote",
    recIndx: "ProductID",
    url: "http://local.pims/product/getproducts/?cat_id=3",
    postData: function () {
        return {
            pq_curpage: pqVS.requestPage,
            pq_rpp: pqVS.rpp
        };
    },
    getData: function (response) {
        var data = response.data;
        var len = data.length;
        var rowBlankData = {
            catAttr_11: "",
            catAttr_13: ""
        }; //empty row template
        for(var k = len;k < len + 5; k++){
            data.push(rowBlankData);
        }
       
        len = data.length;
        var totalRecords = response.totalRecords,
        curPage = response.curPage,
        pq_data = pqVS.data,
        init = (curPage - 1) * pqVS.rpp;
        if (!pqVS.totalRecords) {
            //first time initialize the rows.
            for (var i = len; i < totalRecords; i++) {
                pq_data[i + init] = { pq_empty: true };
            }
            pqVS.totalRecords = totalRecords;
        }
        for (var i = 0; i < len; i++) {
            pq_data[i + init] = data;
            pq_data[i + init].pq_empty = false;
        }
        return { data: pq_data }
    },
    error: function (jqXHR, textStatus, errorThrown) {
        console.log(errorThrown);
    }
};


But when i console variable data then i found that pq_ri is same for all the blank rows. I've attached screenshot for the same, Please check and let me know if i am doing something wrong.

Thanks

paramvir

  • Administrator
  • Hero Member
  • *****
  • Posts: 6309
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #7 on: May 16, 2018, 10:18:33 pm »
It's because you are adding same row 5 times. Rather make a copy everytime you add a new row.

Code: [Select]
var rowBlankData = {
            catAttr_11: "",
            catAttr_13: ""
        }; //empty row template
        for(var k = len;k < len + 5; k++){
            data.push( $.extend({}, rowBlankData) );
        }

or simply

Code: [Select]
        for(var k = len;k < len + 5; k++){
            data.push( {} );
        }

That being said and although it would correct pq_ri of new rows, it doesn't make sense from UX point of view and it might create other problems. When you fetch next page from remote location, its response would overwrite newly added rows.

I see from your code that you have been using virtual scrolling with remote paging and FYI batch editing is incompatible with remote paging as mentioned in demo.

https://paramquery.com/pro/demos/editing_batch

And right way to add new rows along with transactions is to use addRow() API. Directly pushing the rows in data bypasses the transactional functionaliy of grid.
« Last Edit: May 16, 2018, 10:20:55 pm by paramquery »

megastream

  • Pro Deluxe
  • Newbie
  • *
  • Posts: 23
    • View Profile
Re: How can i use Autofill feature with Autosave?
« Reply #8 on: May 17, 2018, 10:13:33 am »
Hi,

Many Many thanks to you to figure out the issues.

I'll follow your instructions and try not to push rows in data as i was not aware that it can create such problems.