最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

arrays - Javascript splice removing wrong items - Stack Overflow

programmeradmin2浏览0评论

I have following array of objects.

[{"name":"Rain"},{"name":"Storm"},{"name":"Forest"}]

Which has indexes [0, 1, 2]. I'm trying to delete the item on the given position using code:

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

But it is removing items wrong way, for example the last item cannot be deleted. If I'm trying to remove item with index 1, it removes item with index 2..

What can be wrong please?

I tried both ways:

$scope.removeSoundFromSelection = function(index) {
    try {
        // First
        $scope.selectedSounds.splice(index, 1);
        var indexNew = $scope.selectedSounds.indexOf(index);
        console.log(indexNew);
        if (indexNew > -1) {
            $scope.selectedSounds.splice(indexNew, 1);
        }

        // Second
        if ($scope.selectedSounds.hasOwnProperty(index)){
            delete $scope.selectedSounds[index];
        }

        //delete $scope.selectedSounds[index];
    } catch(e) {
        $scope.showAlert();
    }
};

ADDED TEMPLATE:

<div class="list">
          <a class="item item-thumbnail-left"  ng-repeat="sound in selectedSounds">
              <img src="cover.jpg">
              <h2>{{sound.name}}</h2>
              <p>TEST</p>
              <div class="customDeleteBtnInList">
                  <button ng-click="removeSoundFromSelection({{$index}})" class="button button-icon icon ion-close-circled"></button>
              </div>
          </a>
      </div>

I have following array of objects.

[{"name":"Rain"},{"name":"Storm"},{"name":"Forest"}]

Which has indexes [0, 1, 2]. I'm trying to delete the item on the given position using code:

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

But it is removing items wrong way, for example the last item cannot be deleted. If I'm trying to remove item with index 1, it removes item with index 2..

What can be wrong please?

I tried both ways:

$scope.removeSoundFromSelection = function(index) {
    try {
        // First
        $scope.selectedSounds.splice(index, 1);
        var indexNew = $scope.selectedSounds.indexOf(index);
        console.log(indexNew);
        if (indexNew > -1) {
            $scope.selectedSounds.splice(indexNew, 1);
        }

        // Second
        if ($scope.selectedSounds.hasOwnProperty(index)){
            delete $scope.selectedSounds[index];
        }

        //delete $scope.selectedSounds[index];
    } catch(e) {
        $scope.showAlert();
    }
};

ADDED TEMPLATE:

<div class="list">
          <a class="item item-thumbnail-left"  ng-repeat="sound in selectedSounds">
              <img src="cover.jpg">
              <h2>{{sound.name}}</h2>
              <p>TEST</p>
              <div class="customDeleteBtnInList">
                  <button ng-click="removeSoundFromSelection({{$index}})" class="button button-icon icon ion-close-circled"></button>
              </div>
          </a>
      </div>
Share Improve this question edited Jan 2, 2015 at 20:13 PSL 124k21 gold badges256 silver badges243 bronze badges asked Jan 2, 2015 at 19:13 redromredrom 11.6k34 gold badges166 silver badges269 bronze badges 4
  • 6 it is not removing the wrong item, it is just shifting the items after the targeted item has been deleted. So item at index 2 is now found at index 1 – Patrick Evans Commented Jan 2, 2015 at 19:15
  • 1 Can you show us more code? How you find index, and are you call splice in a loop? – Thierry Commented Jan 2, 2015 at 19:16
  • What are those conditions if (indexNew > -1) { why do you need it? why are u splicing it and then delete ing as well? SHow us how you are passing the index? If you are using ng-repeat and passing $index you just need $scope.selectedSounds.splice(index, 1);. – PSL Commented Jan 2, 2015 at 19:23
  • Angular schmangular. What is the underlying pure Javascript cause of myArray.splice(0,1) actually removing the element that was initially at index 1 instead of the element that was initially at index 0? – Szczepan Hołyszewski Commented Dec 12, 2015 at 14:01
Add a ment  | 

5 Answers 5

Reset to default 1

You are using interpolation for {{$index}} inside the ng-repeat expression removeSoundFromSelection({{$index}}). Just remove the interpolation and use only $index it will automatically be evaluated against the scope. And you just need $scope.selectedSounds.splice(index, 1).

Ideally using the interpolation there should cause parse error instead of this behavior though (Unless very old angular version, i.e < 1.2.0, is used).

Working Demo

angular.module('app', []).controller('ctrl', function($scope) {
  $scope.selectedSounds = [{
    "name": "Rain"
  }, {
    "name": "Storm"
  }, {
    "name": "Forest"
  }];

  $scope.removeSoundFromSelection = function(index) {

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

  };
});
<script src="https://ajax.googleapis./ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="ctrl">
  <div class="list">
          <a class="item item-thumbnail-left"  ng-repeat="sound in selectedSounds">
              <img src="cover.jpg">
              <h2>{{sound.name}}</h2>
              <p>TEST</p>
              <div class="customDeleteBtnInList">
                  <button ng-click="removeSoundFromSelection($index)" class="button button-icon icon ion-close-circled">Remove</button>
              </div>
          </a>
      </div>
</div>


Even though this specific scenario in the question does not use ng-init the issue of wrong item removed can happen if you are using ng-init initialized index alias as well. Just adding that scenario as well to the answer for any future visitations on this question. i.e example:-

<a class="item item-thumbnail-left"  
    ng-repeat="sound in selectedSounds" ng-init="idx=$index">
   ....
    <button ng-click="removeSoundFromSelection(idx)"

This will end up removing wrong items because ng-init'ed scope properties are not watched and updated during the digest cycle. So even if the item gets removed from DOM after splicing the array ng-inited idx will still have the old index of the item where as $index special property would have got updated to reflect the actual index. So in such cases as well use $index to pass the index instead of using cached ng-inited idx.

You are removing the item at that index twice.

Once here:

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

And once here:

// Second
if($scope.selectedSounds.hasOwnProperty(index)){
    delete $scope.selectedSounds[index];
}

Just remove that second part and you should be fine, I can't see what you could be trying to do after that first splice line.

The following code works as expected for me, and seems to be what you are trying to achieve:

var sounds = [{"name":"Rain"},{"name":"Storm"},{"name":"Forest"}];
sounds.splice(1, 1);

console.log(sounds);

My guess is that you are (at some point) not using the correct index. Take a look at the code that creates that variable per @Alex J's answer

If you want the middle item to be deleted, index should equal 1. It's possible that whatever logic you are doing is giving you the wrong value for index

*Edit: After seeing your updated code, it looks like you are splicing twice. You are doing it the first time in the try statement, and then it goes to the if statement where that will also be true. If you are trying to write a function to just splice out an object at a given index, you could do:

$scope.removeSoundFromSelection = function(index) {
  if($scope.selectedSounds[index]){
    $scope.selectedSounds.splice(index, 1);
  }
}
var season = [{"name":"Rain"},{"name":"Storm"},{"name":"Forest"}];
var seasoned= season.slice(0, 2); 
console.log(seasoned); //it sliced rain and storm...
发布评论

评论列表(0)

  1. 暂无评论