AngularJS:在删除元素时未调用的循环指令,手动触发它?

时间:2015-06-02 12:57:27

标签: angularjs angularjs-directive angularjs-ng-repeat

我在ng-repeat块中有几个输入字段,用户可以使用按钮添加和删除字段。指令用于标记模糊上的无效字段。

我的问题是: 当我在控制器中向模型添加新字段时,一切正常。视图已更新,并再次调用该指令以处理输入字段上的错误。 但是当我从模型中删除Fields时,视图会更新,但指令不会运行。渲染ng-repeat时,函数将绑定到字段的blur事件。 (inputNgEl.bind)。当用户从列表中删除字段时,例如,第2个字段为4时,其余字段将获得新名称,因此必须再次绑定该函数。这就是为什么我需要指令在一个人被移除后再次运行。

我的演示代码:http://plnkr.co/edit/EBggptFsMFld2fMfzS83?p=preview

您可以在控制台中看到添加新字段时如何调用该指令,但在删除它时则不能。

我需要的是一种在控制器的removePersonFields函数中手动触发指令的方法,或者另一种更优雅的解决方案。这可能吗?

这是HTML:

<form novalidate name="form">
  <div ng-repeat="person in persons" >
        <div class="form-group" show-errors errorfieldindex="{{$index}}">
            <label class="control-label">Name ({{'name_'+$index}})</label>
            <input ng-model="person.name" name="name_{{$index}}" required class="form-control">
            <span ng-if="form['name_'+$index].$error.required" class="help-block">Name invalid.</span>
        </div>
        <div class="form-group" show-errors errorfieldindex="{{$index}}">
            <label class="control-label">Mail ({{'email_'+$index}})</label>
            <input type="email" ng-model="person.email" name="email_{{$index}}" required class="form-control">
            <span ng-if="form['email_'+$index].$error.required" class="help-block">Email required.</span>
            <span ng-if="form['email_'+$index].$error.email" class="help-block">EMail invalid.</span>
        </div>
        <div class="btn-group">
            <button type="button" class="btn btn-default" ng-click="removePersonFields($index)" ng-show="persons.length > 1">remove</button>
            <button type="button" class="btn btn-default" ng-click="addPersonFields()">add</button>
        </div>
  </div>    
</form>

相应的控制器:

app.controller('MainCtrl', function($scope) {
  $scope.init = function() {
    $scope.persons = [{name: 'User One', email: 'aaa.bbb@ccc.org'},
                      {name: 'User Two', email: 'ddd.eee@fff.org'}];
  }

  $scope.addPersonFields = function() {
      console.log("add person row");
      $scope.persons.push( {name: '', email: ''});
  }

  $scope.removePersonFields = function(index) {
      console.log("remove person row");
      $scope.persons.splice(index,1);
      // the view is updated after the splice, but the directive does not run.
  }

  $scope.init();
});

每个输入字段都有一个名称,其中包含循环的当前索引。我在指令'show-errors'中使用此名称,以在字段失去焦点时分配和删除css类。该类仅用于隐藏错误消息,直到用户离开输入字段。

指令'showErrors':

app.directive('showErrors', function() {
  return {
      restrict: 'A',
      require:  '^form',
      scope: { 
          errorfieldindex : '@'  
      },
      link: function (scope, el, attrs, formCtrl) {
        console.log("showErrors - link!");
        // find the text box element, which has the 'name' attribute
        var inputEl   = el[0].querySelector("[name]");
        // convert the native text box element to an angular element
        var inputNgEl = angular.element(inputEl);

        // get the name on the text box so we know the property to check      
        // on the form controller
        var inputName = inputNgEl.attr('name');

        if(typeof inputName != 'undefined') {

          console.log("inputName: " + inputName);

          var errorFieldIndex = scope.errorfieldindex;

          if(typeof errorFieldIndex != 'undefined') {
                console.log("errorFieldIndex: " + errorFieldIndex);
              if(inputName.indexOf("{{$index}}") > 0) {
                  console.log("replace {{$index}} with " + errorFieldIndex);
                  inputName = inputName.replace("{{$index}}", errorFieldIndex);
              }
          }
          // only apply the has-error class after the user leaves the text box
          inputNgEl.bind('blur', function() {
              console.log("bind Blur-event on element: " + inputName);
              el.toggleClass('has-error', formCtrl[inputName].$invalid);
          });
      }
    }
  }
});

0 个答案:

没有答案