AngularJS / ng-grid - Updating an array using splicing does not update the user interface

I am trying to update ng-grid with a splice array. I have a plunk here .

Button

Add adds a new line. The refresh button updates the last element of the array.

  • Select a row and click the refresh button. Nothing has happened.
  • Click the add button. Now the user interface is updated with a new element, as well as with a previously updated element.
  • This behavior is repeated over and over.

I tried $scope.$apply . I get:

"Error: $ apply is already running"

I even tried placing the $scope.$apply block inside a setTimeout call. The same mistake again!

Any pointers!

Thanks!

+6
source share
3 answers

This is because the $ watcher data in ng-grid (incorrectly) compares the data object for reference, and not from equality of objects. You can fix this by setting the third parameter to true in the $ watch $ function (line 3128):

 $scope.$parent.$watch(options.data, dataWatcher, true); 

Plunker

+15
source

UPDATE (2015-04-10)

Angular has improved its code base (1.4.0), first try the $scope.$watchCollection and see if it works for you. ( Link )

ANSWER

If you don't like hacking into a third-party library, you can add hacking to your code using:

 $scope.updateData = function() { var data = angular.copy($scope.myData); data.splice(data.length - 1, 1, {name: 'UPDATED', age: '4'}) $scope.myData = data; }; 

plunkr

As @Stewie mentions, the problem is that for performance reasons, ngGrid superficially compares the data object, and in the case of arrays, by reference. ngGrid also compared by the length of the array, so if the array does not change the length, the grid will not be updated.

This solution creates a copy of the array (another location in memory), so when angularjs $watcher checks for changes, it will find another object and run the ngGrid update ngGrid .

NOTE. . Since this solution creates a copy of the data array each time updateData called, it can lead to performance problems if your data is too large and Javascript does not have a lot of garbage collection.

Old wrong answer:

$timeout(angular.noop, 0);

It just sets a timeout to run $scope.$apply() after the current one has completed. A way to force a dirty check.

+4
source

I am using ui-grid v3.0.0 (from the unstable build of April 2015). I found this post and wanted to show others how I updated my grid after I deleted a row from the grid data object using a splice:

 // Remove the row and refresh the grid. $scope.myData.splice(rowIndex, 1); $scope.gridApi.grid.refresh(true); 

where my scope gridApi variable was set using this function:

 $scope.gridOptions.onRegisterApi = function(gridApi){ $scope.gridApi = gridApi; } 
0
source

Source: https://habr.com/ru/post/948952/


All Articles