Angularjs中Splice不起作用

3

我现在尝试制作一个项目列表表单,可以进行添加编辑删除操作。添加和编辑都能正常工作,但是当我尝试删除时,它并没有按照预期工作。

这里是我的代码片段,其中包含删除按钮。

      <!-- Added Items Stage -->
      <div ng-repeat-start="item in items" ng-form="editItemForm" class="row">
        <div class="col">
          <input type="text" name="description" ng-model="item.description" placeholder="description" required>
        </div>
        <div class="col">
          <input type="number" name="quantity" pattern="\d*" ng-model="item.quantity" placeholder="quantity" required>
        </div>
        <div class="col">
          <input type="text" name="price" ng-model="item.price" placeholder="price" required>
        </div>
        <div class="col">
          <select name="taxType" ng-model="item.taxType" required>
            <option value="ZR">ZR</option>
            <option value="SR">SR</option>
          </select>
        </div>
        <div class="col col-20" ng-bind="(item.quantity&&item.price)?((item.quantity*item.price) | currency:''):'0.00'"></div>
        <div class="col col-10">
          <button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem(item)"></button>
        </div>
      </div>

      <hr ng-repeat-end>

第二部分是我如何删除项目

$scope.deleteItem = function(item) {
    $scope.items.splice($scope.items.indexOf(item), 1);
};

我尝试传递$index,或者使用delete代替splice,但它仍然不能正常工作。请帮助我。谢谢。

这是我的演示

注意:我认为项���已被删除,但html没有更新。


2
@异常,不对 - Grundy
@charlietfl,请在您的控制台中检查此内容[{a:1}, {b:2}, {c:34}].indexOf({b:2}),它会显示-1。默认的indexOf不支持它,但我认为Angular正在添加自定义的indexOf函数。如果这样做,它将给您确切的索引[1,2,3,4,6,6].indexOf(4) - Exception
@Grundy 哪个部分有问题。 - Exception
1
@异常,这是因为indexOf中的对象字面量与索引1处的对象不同。尝试使用var b = {b:2}; [{a:1}, b, {c:34}].indexOf(b) - Phil
1
@Edward,我认为你在isolate-form和移除控制器的同时与ng-start-repeat/end-repeat混淆了一些不寻常的事情。 - charlietfl
显示剩余5条评论
4个回答

2

有时候Angular不知道模型已经发生了变化,这种情况下,您可以通过在没有延迟的情况下将函数包装在$timeout中来强制更新:

$scope.deleteItem = function(item) {
    $timeout(function () {
        $scope.items.splice($scope.items.indexOf(item), 1);
    });
};

不要忘记将$timeout服务注入到控制器中。


2
这里不是这种情况。 - Phil
在我的情况下起作用,我给你点赞...非常感谢@R. Kazeno - Lucy

1
我不太明白为什么,但你的问题在于重复器中的ng-form属性。如果你将它移除,所有东西都会正常工作。

var nameApp = angular.module('starter', ['ionic', 'ngMessages']);

nameApp.config(function($stateProvider, $urlRouterProvider) {

  $stateProvider
    .state('auth', {
      url: '/auth',
      templateUrl: 'auth.html',
    })
    .state('home', {
      url: '/home',
      templateUrl: 'home.html',
      controller: 'HomeCtrl'
    });

  $urlRouterProvider.otherwise("/auth");

});


nameApp.directive('isolateForm', [function() {
  return {
    restrict: 'A',
    require: '?form',
    link: function(scope, elm, attrs, ctrl) {
      if (!ctrl) {
        return;
      }

      // Do a copy of the controller
      var ctrlCopy = {};
      angular.copy(ctrl, ctrlCopy);

      // Get the parent of the form
      var parent = elm.parent().controller('form');
      // Remove parent link to the controller
      parent.$removeControl(ctrl);

      // Replace form controller with a "isolated form"
      var isolatedFormCtrl = {
        $setValidity: function(validationToken, isValid, control) {
          ctrlCopy.$setValidity(validationToken, isValid, control);
          parent.$setValidity(validationToken, true, ctrl);
        },
        $setDirty: function() {
          elm.removeClass('ng-pristine').addClass('ng-dirty');
          ctrl.$dirty = true;
          ctrl.$pristine = false;
        },
      };
      angular.extend(ctrl, isolatedFormCtrl);
    }
  };
}]);



nameApp.controller('AuthCtrl', function($scope, $state) {

  $scope.newItem = {
    description: undefined,
    quantity: undefined,
    price: undefined,
    taxType: undefined
  };

  $scope.items = [];

  $scope.addItem = function() {
    console.log({
      description: $scope.newItem.description,
      quantity: $scope.newItem.quantity,
      price: $scope.newItem.price,
      taxType: $scope.newItem.taxType
    });

    $scope.items.push({
      description: $scope.newItem.description,
      quantity: $scope.newItem.quantity,
      price: $scope.newItem.price,
      taxType: $scope.newItem.taxType
    });

    console.log($scope.items);

    $scope.newItem.description = undefined;
    $scope.newItem.quantity = undefined;
    $scope.newItem.price = undefined;
    $scope.newItem.taxType = "SR";

  };

  $scope.deleteItem = function(item) {
    $scope.items.splice($scope.items.indexOf(item), 1);
  };

  $scope.authorization = {
    referenceNo: '',
  };

  $scope.signIn = function(form) {
    if (form.$valid) {
      $state.go('home');
    }
  };

});

nameApp.controller('HomeCtrl', function($scope) {

});
.error-container {
  margin: 5px 0;
}

.error-container:last-child {
    margin: 5px 0 0;
}

.error {
  padding: 10px 16px;
  font-family: "Arial Black", Gadget, sans-serif;
  font-size: 11px;
  text-transform: uppercase;
  color: #555;
  vertical-align: middle;
}

.error i {
  font-size: 24px;
  color: #B83E2C;  
  vertical-align: middle;
}

.last-error-container > .error {
  padding: 10px 16px 0;
}

.has-errors {
  border-bottom: 3px solid #B83E2C;
}

.no-errors {
  border-bottom: 3px solid green;
}
<html ng-app="starter">
 
  <link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet"/>
  <script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-messages.js"></script>  
  
  <ion-nav-bar class="bar-positive">
    <ion-nav-back-button class="button-clear">
      <i class="ion-arrow-left-c"></i> Back
    </ion-nav-back-button>
  </ion-nav-bar>
  
  <ion-nav-view></ion-nav-view>
  
  <script id="auth.html" type="text/ng-template">
    <ion-view view-title="Authorization Page">  
    
      <ion-content class="padding" ng-controller="AuthCtrl">
      
        <h2 style="text-align: center;">Form validation example</h2><br/>
        
        <form name="newDocumentForm" ng-submit="signIn(newDocumentForm)" novalidate>
        
          <div class="list">
          
            <label class="item item-input" ng-class="{ 'has-errors' : newDocumentForm.referenceNo.$invalid && newDocumentForm.$submitted, 'no-errors' : newDocumentForm.referenceNo.$valid  && newDocumentForm.$submitted}">
              <span class="input-label">Reference No</span>
              <input type="text" name="referenceNo" ng-model="authorization.username" ng-minlength="5" ng-maxlength="20" required>
            </label>
            
            <div class="error-container" ng-show="newDocumentForm.referenceNo.$error && newDocumentForm.$submitted" ng-messages="newDocumentForm.referenceNo.$error">
              <div ng-messages-include="error-list.html"></div>
            </div>
            
          </div>
        
          <!-- Title -->
          <div class="row">
            <div class="col">Description</div>
            <div class="col">Quantity</div>
            <div class="col">Price</div>
            <div class="col">Tax Type</div>
            <div class="col col-20">Amount</div>
            <div class="col col-10"></div>
          </div>
     
          <!-- Added Items Stage -->
          <div ng-repeat-start="item in items" class="row">
            <div class="col">
              <input type="text" name="description" ng-model="item.description" placeholder="description" required>
            </div>
            <div class="col">
              <input type="number" name="quantity" pattern="\d*" ng-model="item.quantity" placeholder="quantity" required>
            </div>
            <div class="col">
              <input type="text" name="price" ng-model="item.price" placeholder="price" required>
            </div>
            <div class="col">
              <select name="taxType" ng-model="item.taxType" required>
                <option value="ZR">ZR</option>
                <option value="SR">SR</option>
              </select>
            </div>
            <div class="col col-20" ng-bind="(item.quantity&&item.price)?((item.quantity*item.price) | currency:''):'0.00'"></div>
            <div class="col col-10">
              <button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem(item)"></button>
            </div>
          </div>
          
          <hr ng-repeat-end>
          
     <!-- Adding Stage -->
          <div ng-form="addItemForm" class="row" isolate-form>
            <div class="col">
              <input type="text" name="description" ng-model="newItem.description" placeholder="description" required/>
            </div>
            <div class="col">
              <input type="number" pattern="\d*" name="quantity" ng-model="newItem.quantity" placeholder="quantity" required/>
            </div>
            <div class="col">
              <!--<input type="text" name="price" ng-model="newItem.price" placeholder="price" ng-pattern="/^[0-9]{1,7}$/" required/>-->
              <input type="text" name="price" ng-model="newItem.price" placeholder="price" step="0.01" ng-pattern="/^[0-9]+(\.[0-9]{1,2})?$/" required/>
            </div>
            <div class="col">
              <select name="taxType" ng-model="newItem.taxType" required>
                <option value="ZR">ZR</option>
                <option value="SR">SR</option>
              </select>
            </div>
            <div class="col col-20" ng-bind="(newItem.quantity&&newItem.price)?((newItem.quantity*newItem.price) | currency:''):'0.00'"></div>
            <div class="col col-10">
              <button type="button" ng-disabled="addItemForm.$invalid" class="button button-balanced button-clear icon ion-plus-circled" ng-click="addItem()"></button>
            </div>
          </div>
            
          <div class="error-container last-error-container" ng-show="addItemForm.price.$error.pattern" ng-messages="addItemForm.price.$error">
            <div ng-messages-include="currency-error-list.html"></div>
          </div>
          
          <button class="button button-full button-positive" type="submit">
            Submit
          </button>
            
        </form>   
        
      </ion-content>
      
    </ion-view>
  </script>  
  
  <script id="home.html" type="text/ng-template">
    <ion-view view-title="Second page">
      <ion-content class="padding">
          <h1>Wellcome</h1>
      </ion-content>
    </ion-view>
  </script>   

  <script id="currency-error-list.html" type="text/ng-template">  
    <div class="error" ng-message="pattern">
      <i class="ion-information-circled"></i> 
      Invalid currency format!
    </div>
  </script> 

  <script id="error-list.html" type="text/ng-template">  
    <div class="error" ng-message="required">
      <i class="ion-information-circled"></i> 
      This field is required!
    </div>
    <div class="error" ng-message="minlength">
      <i class="ion-information-circled"></i> 
      Minimum length of this field is 5 characters!
    </div>
    <div class="error" ng-message="maxlength">
      <i class="ion-information-circled"></i> 
      Maximum length of this field is 20 characters!
    </div>
  </script>   


可能更容易的做法是直接链接到修改后的 Plunker ~ http://plnkr.co/edit/gAk1wONFKFosoEwGOQzn?p=preview - Phil
@Phil,在代码片段中,很明显一切都正常 :-) 可能是某些内部的 ng-form 阻止了视图更新,你能否解释一下这个问题? - Grundy
我发现 Stack Overflow 的代码片段会导致答案变得凌乱,因为有许多额外的部分(CSS,第三方库等)。我认为问题很可能是由于作用域冲突引起的。ngRepeat的作用域是复杂的;它不一定是一个新的作用域,也不是隔离作用域。 - Phil
如果不深入研究ngRepeatngForm的代码,我只能猜测。如果可以在简单的示例中重现它,我会将其提交为错误。 - Phil
1
@Phil,似乎这个问题出现在使用嵌套的ng-formng-modelrequiredionic中:http://plnkr.co/edit/7edJiUiMO7DydRCK4ref?p=preview 这是我认为的最小示例。 - Grundy
显示剩余3条评论

0

遇到了同样的问题:“Splice不起作用”。在我的情况下,我必须像下面这样解决,以防有人需要帮助。

如果你正在处理对象,请注意'indexOf'只适用于数组而不适用于数组中的对象。您可以像下面这样做来识别索引并处理此情况;

$scope.removeReport = function(report) {
    var index = $scope.contact.reports.map(function(r) { return r.id;}).indexOf(report.id);
        if (index >= 0) {
          $scope.contact.reports.splice(index, 1);
        }
}

-2

使用 Index 代替 Item

<button type="button" class="button button-assertive button-clear icon ion-close-circled" ng-click="deleteItem($index)"></button>

同样在控制器中

$scope.deleteItem = function(index) {
    $scope.items.splice(index, 1);
};

3
如果你尝试一下,就会发现在这种情况下这并不起作用。 - Grundy
这肯定会100%起作用。 - KunwarAnil
你在 OP 的示例中试过了吗? :-) - Grundy

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