angular-ui / ui-grid

UI Grid: an Angular Data Grid
http://ui-grid.info
MIT License
5.39k stars 2.47k forks source link

Importer Error(with rowEdit) - angular.min.js:108 requested row not found in rowEdit.setRowsDirty, row was: [object Object] #5815

Open atatchin opened 7 years ago

atatchin commented 7 years ago

Implemented Importer functionality and everything works fine except when I get the following error on the console from adding new row to the grid on this line of code - allRows.unshift({

Error message: angular.min.js:108 requested row not found in rowEdit.setRowsDirty, row was: [object Object]

importerDataAddCallback: function (grid, newObjects) { var errorPRLS = ""; var errors = 0;

                if (newObjects) {                      
                    var cnt = newObjects.length;                
                    //turn on cancel button
                    grid.appScope.trigger.insert = true;
                    grid.appScope.trigger.importer = true;
                    var allRows = this.data;

                    angular.forEach(newObjects, function (row, index) {
                        PrecutReplenishmentService.requestId = row.precutPartNumber;
                        PrecutReplenishmentService.doGetMaster().success(function (response) {
                                if (response.data !== null) {
                                    if (typeof response.data.successful !== 'undefined' && !response.data.successful) {
                                        errorPRLS = errorPRLS == "" ? row.precutPartNumber : errorPRLS + ", " + row.precutPartNumber;
                                        errors++;
                                    } else {
                                            //instantiate local object
                                            var pRLColorDetail = new Object();
                                            pRLColorDetail.id = grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].id;
                                            pRLColorDetail.pRLColor = grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].pRLColor;
                                            //add to the top of collection
                                            allRows.unshift({
                                                id: 0,
                                                pRLColorId: grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].id, //default data entity row to yellow
                                                pRLColorDetails: pRLColorDetail, //default data editor to yellow
                                                precutPartNumber: row.precutPartNumber,
                                                piecesToCut: row.piecesToCut,
                                                masterPartNumber: response.data.precutMaster,
                                                isDrill: response.data.isDrill,
                                                scheduledCutDate: grid.appScope.getCutDate()
                                            });
                                            //add to save counter
                                            grid.appScope.trigger.records++;
                                            //fire after all promisses have been resolved
                                            if (grid.appScope.trigger.records > 0) {
                                                if (cnt == grid.appScope.trigger.records + errors) {
                                                    $interval(function () {
                                                         var gridRows = grid.rows.filter(function (element) { return element.entity.id == 0 });
                                                         var dataRows = gridRows.map(function (gridRow) { return gridRow.entity; });
                                                         grid.api.rowEdit.setRowsDirty(dataRows); 
jstallm commented 7 years ago

noticed this today. Noticed it only happens on a custom dropdown control, and completely unreleated to any Importer..

emanuel-virca commented 7 years ago

I have had the same error and fixed it by waiting to be notified by grid that data has been changed and only then setting the rows as dirty var dataChangeDereg = self.gridApi.grid.registerDataChangeCallback(function() { self.setRowsDirty(rows); dataChangeDereg(); }, [uiGridConstants.dataChange.ROW]);

atatchin commented 7 years ago

Emanuel,

I would have to implement this callback feature onRegisterApi... am I correct?

onRegisterApi: function (gridApi) {

$scope.gridApi = gridApi;

dataChangeDereg = self.gridApi.grid.registerDataChangeCallback(function () {

self.setRowsDirty(rows);

dataChangeDereg();

}, [uiGridConstants.dataChange.ROW]);

On Tue, Feb 14, 2017 at 6:05 AM, Emanuel Virca notifications@github.com wrote:

I have had the same error and fixed it by waiting to be notified by grid that data has been changed and only then setting the rows as dirty var dataChangeDereg = self.gridApi.grid.registerDataChangeCallback(function() { self.setRowsDirty(rows); dataChangeDereg(); }, [uiGridConstants.dataChange.ROW]);

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/angular-ui/ui-grid/issues/5815#issuecomment-279690246, or mute the thread https://github.com/notifications/unsubscribe-auth/ANiIxFVYE8Z7EeHrafvrqfwYismoXKDoks5rcZh0gaJpZM4KzEub .

emanuel-virca commented 7 years ago

Hello @atatchin you should implement the callback feature before adding new rows to grid, just make sure you add new rows after the RegisterApi is called as you neeed acces to gridApi .

addNewData: function(data) {
         var self = this;
         dataChangeDereg = self.gridApi.grid.registerDataChangeCallback(function() {
                 self.gridApi.rowEdit.setRowsDirty(data);
                 dataChangeDereg();
           }, [uiGridConstants.dataChange.ROW]);

          self.gridOptions.data = self.gridOptions.data.concat(data);
 }

Just to mention, I am not using the build in import because I need to import from excel which is not supported. I am registering the callback before adding new rows to gridOptions.data. Here is the complete method

emanuel-virca commented 7 years ago

Ui-grid importer is smart enough to wait for new objects to be added to grid and than sets the rows as dirty. See source code below:

 addObjects: function( grid, newObjects, $scope ){
          if ( grid.api.rowEdit ){
            var dataChangeDereg = grid.registerDataChangeCallback( function() {
              grid.api.rowEdit.setRowsDirty( newObjects );
              dataChangeDereg();
            }, [uiGridConstants.dataChange.ROW] );

            grid.importer.$scope.$on( '$destroy', dataChangeDereg );
          }

          grid.importer.$scope.$apply( grid.options.importerDataAddCallback( grid, newObjects ) );

        },

If you add each row at once the function registered with registerDataChangeCallback will only execute once for that specific row and then will be deregistered. All the other entities will not be marked as dirty and that's why you have to set them manually. One approach would be to add newObjects at once in grid.data by calling gridOptions.data = [].concat(newObjects , gridOptions.data); //add to the top of collection You now do not have to worry about setting those rows as dirty as ui-grid does this for you. All you have to do from now on in your case is just filter the gridOptions.data to find the rows with id=0 and call PrecutReplenishmentService.doGetMaster() for it. Then only update the properties to the new values

Here is the solution:

importerDataAddCallback: function (grid, newObjects) {
    var errorPRLS = "";
    var errors = 0;

    if (newObjects) {                     

        //turn on cancel button
        grid.appScope.trigger.insert = true;
        grid.appScope.trigger.importer = true;

        this.data = [].concat(newObjects , this.data); //add to the top of collection` 

        angular.forEach(this.data.filter(function (x){ return !x.id})), function (row, index) {
            PrecutReplenishmentService.requestId = row.precutPartNumber;
            PrecutReplenishmentService.doGetMaster().success(function (response) {
                if (response.data !== null) {
                    if (typeof response.data.successful !== 'undefined' && !response.data.successful) {
                        errorPRLS = errorPRLS == "" ? row.precutPartNumber : errorPRLS + ", " + row.precutPartNumber;
                        errors++;
                    } else {
                        //instantiate local object
                        var pRLColorDetail = new Object();
                        pRLColorDetail.id = grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].id;
                        pRLColorDetail.pRLColor = grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].pRLColor;
                        //add to the top of collection
                        var computedObject={
                            id: 0,
                            pRLColorId: grid.appScope.prlColors[grid.appScope.trigger.setColorIndex].id, //default data entity row to yellow
                            pRLColorDetails: pRLColorDetail, //default data editor to yellow
                            precutPartNumber: row.precutPartNumber,
                            piecesToCut: row.piecesToCut,
                            masterPartNumber: response.data.precutMaster,
                            isDrill: response.data.isDrill,
                            scheduledCutDate: grid.appScope.getCutDate()
                        }
                        angular.extend(row, computedObject);
                        //add to save counter
                        grid.appScope.trigger.records++;

Hope it helps

atatchin commented 7 years ago

Emanuel,

Thank you so much, I implemented your solution and the error is gone....

You are the best....

On Wed, Feb 15, 2017 at 2:53 AM, Emanuel Virca notifications@github.com wrote:

Hello @atatchin https://github.com/atatchin you should implement the callback feature before adding new rows to grid, just make sure you add new rows after the RegisterApi is called as you neeed acces to gridApi . `addNewData: function(data) { var self = this; dataChangeDereg = self.gridApi.grid.registerDataChangeCallback(function() { self.processNewAddedRows(data); dataChangeDereg(); }, [uiGridConstants.dataChange.ROW]);

  self.gridOptions.data = self.gridOptions.data.concat(data);

}

Just to mention, I am not using the build in import because I need to import from excel which is not supported. I am registering the callback before adding new rows to gridOptions.data. Here is the complete method

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/angular-ui/ui-grid/issues/5815#issuecomment-279952216, or mute the thread https://github.com/notifications/unsubscribe-auth/ANiIxPz4ORJT2k9PR34UcdumzYdUVcQ5ks5rcr0DgaJpZM4KzEub .