指令导致$ scope在触发时未定义

时间:2016-09-07 13:46:08

标签: angularjs mongodb angular-meteor

今天,我尝试用角度编写一个指令,纯粹是为了让我自己"检查这封电子邮件是否存在"验证

然而,当指令运行时,它会清除范围 - 使其未定义,我没有烹饪线索的原因。当我尝试提交表单时,禁用该指令会导致我的范围不会丢失。任何人都可以向我解释为什么会这样做?

我的HTML:

<form class='form-horizontal' name="userForm" novalidate>
    <div class='form-group' ng-class="{ 'has-error' : userForm.emailAddress.$invalid && !userForm.emailAddress.$pristine }">
        <div class="col-sm-3">
          <label class="control-label" for='emailAddress'>Email Address: </label>
        </div>
        <div class="col-sm-6">
          <input class='form-control' type='email' id='emailAddress' name='emailAddress' ng-model='letMeKnowEmail' email-exists required/>
          <p ng-show="userForm.emailAddress.$error.required && !userForm.emailAddress.$pristine" class=".input-error">Your email is required.</p>
          <p ng-show="userForm.emailAddress.$error.email && !userForm.emailAddress.$pristine" class=".input-error">Your email is in an invalid format.</p>
          <p ng-show="userForm.emailAddress.$error.emailExists && !userForm.emailAddress.$pristine" class=".input-error">This email already exists.</p>
        </div>
        <div class="col-sm-3">
          <button class='btn btn-theme' ng-disabled="userForm.$invalid" ng-click='userForm.$invalid || addEmail(letMeKnowEmail)'>Let Me Know!</button>
        </div>
    </div>
</form>

我的角度JS文件:

/* dependancies */
import angular from 'angular';
import angularMeteor from 'angular-meteor';
import uiRouter from 'angular-ui-router';

/* templates */
import template from './applicationProcessTemp.html';

class ApplicationProcessTempCtrl {
  constructor($scope, $reactive) {
    $reactive(this).attach($scope);
    $scope.letMeKnowEmail = '';
    $scope.addEmail = function(letMeKnowEmail) {
      if (this.userForm.$valid) {
        SiteInterestShown.insert({
          email: letMeKnowEmail
        });
      }
    }
  }
}

const name = 'applicationProcessTemp';
ApplicationProcessTempCtrl.$inject = ['$scope', '$reactive'];

export default angular.module(name, [
    angularMeteor
  ]).component(name, {
    template,
    controllerAs: name,
      controller: ApplicationProcessTempCtrl
  }).config(config)
  .directive('emailExists', directive);

function config($stateProvider) {
  'ngInject';

  $stateProvider.state('applicationTemp', {
    url: '/applicationTemp',
    template: '<application-process-temp></application-process-temp>'
  });
}

config.$inject = ['$stateProvider'];

function directive($timeout, $q) {
  return {
    restrict: 'AE',
    require: 'ngModel',
    link: function(scope, elm, attr, model) {
      model.$asyncValidators.emailExists = function() {
        var defer = $q.defer();
        $timeout(function() {
          var exists = SiteInterestShown.findOne({
            'email': model.$viewValue
          }) == undefined;
          model.$setValidity('emailExists', exists);
          defer.resolve;
        }, 1);
        return defer.promise;
      }
    }
  }
}

directive.$inject = ['$timeout', '$q'];

环境是一个流星环境,但是我非常怀疑流星导致我的范围未定义在指令触发时验证电子邮件是否存在。我怀疑minimongo可能参与了这个问题(SiteInterestShown变量是在项目根目录的collections文件夹中设置的mongo集合)

1 个答案:

答案 0 :(得分:0)

model.$asyncValidators.emailExists = function(modelValue, viewValue) {
        var deferred = $q.defer();
        var value = modelValue || viewValue;

        var checkVal = model.$viewValue;
        var exists = SiteInterestShown.findOne({
          'email': value
        }) != undefined;

        if (!exists) {
          deferred.resolve(); <-- resolve was a method. called it as a method on validation success.
        } else {
          deferred.reject();  <-- reject would destroy the binding value and as far as I see, it gets auto-called if resolve() isn't fired.
        }

        return deferred.promise;
}

此代码段面临的问题是我将resolve称为属性,而不是方法。我还删除了一些额外的代码($ timeout),因为我认为这是不必要的 - 但不是错误的 - 在这个示例中。当我打电话给resolve()时,当延期的承诺被退回时,有角度的东西并没有从我的范围中删除价值 - 这是我误解的另一件事。被销毁的"$scope"不是整个范围,只有范围变量绑定到元素作为其模型,因为resolve()不是&#39 ; t叫 - 理论在这里,它自动调用reject()来废除价值。

长话短说 - 我可以再次访问我的范围变量:)