0

I am retrieving an entire "collection" from my mongodb database as array of json objects, "tests".

The "tests" is in following format

[{...},{...},{...}]

I am using this array to populate a table in html using ng-repeat in angularjs.

      <table class="table table-bordered">
        <thead class="thead-dark">
          <tr>
            <th scope="col">#</th>
            <th scope="col">Title</th>
            <th scope="col">Start Date</th>
            <th scope="col">End Date</th>
            <th scope="col">Time</th>
            <th scope="col">Duration</th>
            <th scope="col">Total Marks</th>
            <th scope="col">Pass Marks</th>
            <th scope="col"></th>
            <th scope="col"></th>
          </tr>
        </thead>
        <tbody>
          <tr data-ng-repeat="test in tests" id="testId_{{$index}}">
            <th scope="row">{{$index}}</th>
            <td>{{test.title}}</td>
            <td>{{test.startDate}}</td>
            <td>{{test.endDate}}</td>
            <td>{{test.startTime}}</td>
            <td>{{test.duration}}</td>
            <td>{{test.totalMarks}}</td>
            <td>{{test.passMarks}}</td>
            <td><a href="#" ng-click="deleteTest($index)" class="">Delete</a></td>
            <td><a href="#" ng-click="modifyTest($index)" class="">Modify</a></td>
          </tr>
        </tbody>
      </table>

Which works correctly.

enter image description here I can also add more "collections" to the database and the table grows. But I want to delete "collections" as well from the database and the table must shrink.

Here is the (little messy) controller doing this,

examApp.controller('adminSetTestsController', ['$element', '$compile', '$scope', 'store', '$state', 'Service', 'userAuth', 'testService', function($element, $compile, $scope, store, $state, Service, userAuth, testService) {
    var testId = userAuth.getTestId();
    $scope.tests = [];

    testService.retrieveTest() //service to get all the collections in the db using "testModel.find({});"
    .then(function(response){
       $scope.tests = response;
       console.log('retrieveTest-response:',response);
    })
    .catch(function(error) {console.log('err:',error)});

    $scope.deleteTest = function(index){
       $scope.$index = index;
       var testId = $scope.tests[$scope.$index]._id;
       console.log('testId:',testId);

       $scope.tests.splice(index, 1);

       //Comment this deletion part and the error vanishes.
       testService.deleteTest(testId) //service to delete the "collection" with _id == testId.
       .then(function(response){
           $scope.tests = response;
           console.log('deleteTest-response:',response);
       })
       .catch(function(error) {console.log('err:',error)})
    }
}])

Again it works, but also gives this error.

enter image description here

The error pops up whenever the delete operation is performed.

The error vanishes if the "collection" deleting part of the code is commented out.
So I guess it has to do something with deletion of database collection which is associated with ng-repeat.

I have tried solutions provided in https://docs.angularjs.org/api/ng/directive/ngRepeat, How to remove object from array within ng-repeat with AngularJS? and some other but they all seem to be talking about deleting an item from the array not the database.

Assume that I am pretty new at angularjs.

rsonx
  • 436
  • 7
  • 16

1 Answers1

0

First the actual problem is described here.

Basically AngularJs does not like duplicate objects in their loops.

So changing this line:

<tr data-ng-repeat="test in tests" id="testId_{{$index}}">

Into this:

<tr data-ng-repeat="test in tests track by $index" id="testId_{{$index}}">

This follows the recommended practice for ng-repeat from the AngularJs docs

Best Practice: If you are working with objects that have a unique identifier property, you should track by this identifier instead of the object instance, e.g. item in items track by item.id. Should you reload your data later, ngRepeat will not have to rebuild the DOM elements for items it has already rendered, even if the JavaScript objects in the collection have been substituted for new ones. For large collections, this significantly improves rendering performance.

Tom Slabbaert
  • 21,288
  • 10
  • 30
  • 43