0
votes

I am working on a Angular Material site and using ng-repeat to populate a table. The list generated by the ng-repeat contains a list of users (the users array is populated by a RESTFul query).

Each "item-content" of the ng-repeat has a "Delete" button to delete/splice the item/user out of the array.

If I have no filters applied to the ng-repeat statement...when I splice the index of the selected user out of the array....the UI/DOM is updated and the user is removed from the list.

If I apply a filter (filters by the first letter of the last name and only shows those results)...when I splice the index out of the array...the UI/DOM is NOT updated and user remains in the list (from what I can tell from walking through the delete function from the console...the array is updated and the index/user is removed).

I filter being used is a custom angular filter and takes one input (the starting letter of the last name you want to filter on).

app.filter('startsWith', function () {
return function (items, letterMatch) {
    var re = new RegExp("^[" + letterMatch.toUpperCase() + letterMatch.toLowerCase() + "]$");
    var filtered = [];
    for (var i = 0; i < items.length; i++) {
      var item = items[i];
      var lastNameLetter = item.user.name.substr(item.user.name.indexOf(' ') + 1, 1);

      if (re.test(lastNameLetter)) {
        filtered.push(item);
      }
    }
    return filtered;
};
});

Here is the ng-repeat statement:

 <md-item ng-repeat="user in ddUsers | startsWith:selectedFilter | startFrom:currentPage*pageSize | limitTo:pageSize">

In the controller...I am using Dialog Prompt (part of the Angular Material 1.1 RC framework) to initiate/confirm the Delete and proceed with the splice.

$scope.showPrompt = function(ev,index,user) {
// Appending dialog to document.body to cover sidenav in docs app
var confirm = $mdDialog.prompt()
      .title('Delete User?')
      .textContent('Type in DELETE to confirm deletion of the user.')
      .placeholder('DELETE')
      .ariaLabel('Delete User')
      .targetEvent(ev)
      .ok('Delete')
      .cancel('Cancel');

$mdDialog.show(confirm).then(function(result) {
  if(result=="DELETE")
  {
    $scope.ddUsers.splice(index, 1);
    $scope.showSimpleToast('Successfully deleted ' + user.user.name);
  }
  else
  {
    $scope.showSimpleToast('Did not confirm properly');
  }      
}, function() {
  $scope.showSimpleToast('Cancelled deletion for ' + user.user.name);
  //var message = $scope.filterLastName(user.user.name);
  //$scope.showSimpleToast(message);
});};

When the controller loads...I have a init function that executes and populates ddUsers from a custom angular factory:

var init = function () {
$scope.ddUsers = $UserList.UserList;
}
init();

I am not sure why ng-repeat is not updating after the splice when a filter is applied. If I have no filter on the ng-repeat, ng-repeat does update the UI/DOM to reflect the change and you don't see the user anymore.

1

1 Answers

0
votes

While it is not shown how you call the function I assume you are passing in $index from view.

The problem with doing that is that $index will not be the same index for filtered array as for the original array so you would be splicing the wrong element out of the main data array

You need to do your own indexing by passing in the actual object.

I will also assume that user is that object so you would do:

 if(result=="DELETE")
  {
    var idx = $scope.ddUsers.indexOf(user);
    if(idx > -1 ){// make sure can index this object
       $scope.ddUsers.splice(idx, 1);
       $scope.showSimpleToast('Successfully deleted ' + user.user.name);
    else{
      // Ooops ... can't find it 
    }
  }