Angular - splice函数总是删除最后一个元素

3
我有一个对象数组,当点击删除键时,我想要删除某些对象。然而,它总是从行数组中删除最后一项,无论我创建了多少行。即使我明确地添加了一行代码,例如 $scope.rows.splice(1,1),它仍然会删除最后一个元素,而不是第二个。
JS
angular.module('app', ['ngAnimate', 'ui.bootstrap'])
  .directive('queryBuilder', function() {
    return {
      restrict: 'E',
      scope: {},
      controller: function($scope) {
        $scope.rows = [{}]

        $scope.$on('addRowRqst', function(evt) {
          // evt.stopPropagation()
          $scope.rows.push({})
        });
        $scope.$on('removeRowRqst', function(evt, args) {
          // evt.stopPropagation()
          //THIS IS WHERE THE REMOVE HAPPENS 
          $scope.rows.splice($scope.rows.indexOf(args),1);
        });        
      },
      templateUrl: 'queryBuilderTemplate.html',
    }
  }).directive('queryRow', function() {
    return {
      scope: {},
      restrict: 'EA',
      templateUrl: 'queryRowTemplate.html',
      controller: function($scope) {
        $scope.addRqst = function() {
          $scope.$emit('addRowRqst')
        };
        $scope.removeRqst = function(index) {
          $scope.$emit('removeRowRqst', index)
        };
      },
      link: function(scope, elem, attrs) {

      }
    }
  });

HTML的相关片段
....
<button class="btn btn-default" ng-click="removeRqst($parent.row)" type="submit">Delete Row</button>
....

Plunker:http://plnkr.co/edit/rDkXpIgiOSoNvLNPsVbP

测试:点击“Add Row” 三次,然后在第二行上点击“Delete”。您会发现它实际上删除了第三行而不是第二行。


你的 Plunker 似乎运行良好。你如何检查哪个项目被移除了?请注意,你没有将输入绑定到对象上。 - Zsolt Gyöngyösi
请查看我上面的测试注释。问题不在于删除,而在于删除正确的内容。 - user1142130
Plunker更明确:http://plnkr.co/edit/IZN3XJMpJMyhrw1sEgOk 它运行良好。 - Zsolt Gyöngyösi
它总是删除最后一行 - New Alexandria
没错,我不希望它总是删除最后一行。我希望它删除我点击“删除”按钮的特定行。 - user1142130
什么是args?你确定indexOf找到它而不是返回-1吗?它是如何调用的?'removeRqst'!='removeRowRqst'。 - George Houpis
2个回答

1
代码没问题,正确的表单已被删除。问题在于你没有将视图绑定到queryRow指令,因此似乎最后一个被删除了。实际上,Angular会根据数组重建你的视图,不知道模板内容。因此未绑定的输入字段只是保留值,除了最后一个。

有趣,我不太确定我理解未绑定字段保留其值的部分。例如,当我没有将视图绑定到模型时,如果我在文本输入中输入了一些内容,它仍然会保留在那里。所以你是说,如果我有3行,在第2行中有文本“abc”- Angular会重新绘制它并将“abc”放在第2行吗? - user1142130
请查看此Plunkr:http://plnkr.co/edit/QrXMMU58IV4rJSG0T0n7?p=preview 为了验证正确的表单已被删除,但输入字段仍保留值,而不应该这样。 - Yerken
现在看这个:http://plnkr.co/edit/dSaePFJzXnF0kl2cTsMA?p=preview 正常工作。 - Yerken
问题出现的原因是,你所看到的内容是从父控制器中渲染出来的,该控制器在你的 queryBuilder 中定义。所有子视图都是基于数组迭代进行渲染的。每当你对数组进行更改时,Angular 就会简单地遍历整个数组并删除/插入缺失的内容。由于子指令和父指令之间没有对象引用依赖关系,因此最后一项被删除了。希望这样能够消除困惑 :) - Yerken
顺便说一句,我的答案应该被接受,因为它解释了问题出现的原因,而不仅仅展示了神奇的修复方法 :) - Yerken

1

为了明确@ZsoltGyöngyösi所给出的答案:

每个带有id字段的元素都需要ng-model="$parent.row.field"

因此,如果您按照以下方式设置queryRowTemplate.hml,将会删除正确的行:

queryRowTemplate.html

<div class="form-group col-md-3">
  <label for="selectedField">Select Field</label>
  <select id="selectedField" class="form-control" ng-model="$parent.row.field">
    <option>title</option>
    <option>application</option>
    <option>subject</option>
    <option>filetype</option>
  </select>
</div>
<div class="form-group col-md-3">
  <label for="logicalOperator">Logical Operator</label>
  <select id="logicalOperator" class="form-control" ng-model="$parent.row.logical">
    <option>equal to</option>
    <option>not equal to</option>
  </select>
</div>
<div class="form-group col-md-3">
  <label for="searchText">Search</label>
  <input id="searchText" class="form-control" type="text" placeholder="search..." ng-model="$parent.row.search" />
</div>
<div class="form-group col-md-3">
  <label for="operator">Operator (optional)</label>
  <select id="operator" class="form-control" ng-model="$parent.row.operator">
    <option value=""></option>
    <option>AND</option>
    <option>OR</option>
  </select>
</div>
<button class="btn btn-default" ng-click="addRqst()" type="submit">Add Row</button>
<button class="btn btn-default" ng-click="removeRqst($parent.row)" type="submit">Delete Row</button>
{{$parent.$index}}
<hr />

在此查看Plunkr


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接