简体   繁体   中英

Angular Array of objects, when splicing by index it always removes last element

I have some controllers like this:

app.controller("zipController", function($scope, $http, $rootScope, $timeout) {
  $scope.zipCodes = [];
  $scope.addZipCode = function() {
    $scope.zipCodes.push({code: '', distance: '25mi'});
  }
  $scope.removeZipCode = function(index) {
    console.log(index, 'index removing');
    $scope.zipCodes.splice(index, 1);
  }
});

app.controller("zipCodeController", function($scope, $http, $rootScope, $timeout) {

});

Here is the HTML:

<label ng-click="addZipCodes=!addZipCodes; addZipCode();"><i class="fa fa-map-marker" aria-hidden="true"></i> Target Zip Codes <small>(Cities)</small></label>
<span ng-if="addZipCodes" style="white-space: normal;">
    <span ng-repeat="code in zipCodes track by $index" class="zipCodeInput" ng-controller="zipCodeController">
        <span class="zipCodeText">
            <input type="text" placeholder="Zip Code" ng-model="zipCode" class="zipCode">
        </span>
        <span class="zipCodeSelect">
            <select ng-model="zipCodeDistance" ng-value="code.distance" class="zipCodeDistance">
                <option value="25mi">25 miles</option>
                <option value="50mi">50 miles</option>
                <option value="100mi">100 miles</option>
            </select>
        </span>
        <span class="zipCodeRemove">
            {{$index}}
            <a ng-click="removeZipCode($index)">x</a>
        </span>
    </span>
    <label ng-click="addZipCode();" class="addZipCode"><i class="fa fa-plus-square" aria-hidden="true"></i> Add</label>
</span>

When I call the removeZipCode($index) function it has the correct index, however it always removes the last $scope.zipCodes from the array, not the correct zip code index.

Any ideas why?

Remove "track by $index". it will work.

you could use this

ng-repeat="(index,value) in array"

The ng-model directives inside the ng-repeat are breaking the rule: always have a dot " . " in your ng-models

<span ng-if="addZipCodes" style="white-space: normal;">
    <span ng-repeat="item in zipCodes track by $index" class="zipCodeInput" ng-controller="zipCodeController">
        <span class="zipCodeText">
            <!-- REMOVE 
            <input type="text" placeholder="Zip Code" ng-model="zipCode" class="zipCode">
            -->
            <!-- always have a dot in your ng-model -->
            <input type="text" placeholder="Zip Code" ng-model="item.code" class="zipCode">
        </span>
        <span class="zipCodeSelect">
            <!-- REMOVE
            <select ng-model="zipCodeDistance" ng-value="code.distance" class="zipCodeDistance">
            -->
            <!-- always have a dot in your ng-model -->
            <select ng-model="item.distance" ng-value="item.distance" class="zipCodeDistance">
                <option value="25mi">25 miles</option>
                <option value="50mi">50 miles</option>
                <option value="100mi">100 miles</option>
            </select>
        </span>
        <span class="zipCodeRemove">
            {{$index}}
            <a ng-click="removeZipCode($index)">x</a>
        </span>
    </span>
    <label ng-click="addZipCode();" class="addZipCode"><i class="fa fa-plus-square" aria-hidden="true"></i> Add</label>
</span>

Because the ng-repeat directive creates a child scope for each item, when an ng-model directive omits a dot . , the model modifies items on the child scope and not the parent scope.

For more information, see AngularJS Wiki - The Nuances of Scope Prototypal Inheritance .

The DEMO on JSFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM