使用服务更新ng-change上的焦点元素ng-class

时间:2016-03-23 17:48:57

标签: javascript angularjs

我想让我的服务能够处理任何输入字段。目前我手动编写所有内容,它开始相当于大量的手工工作。有没有办法在调用元素ng-change属性时发送元素对象?然后我可以更改元素ng-class。

HTML:

<input type="text" id="email" data-ng-model="email" data-ng-change="changeEmail()" placeholder="your email here" data-ng-class="emailFormControlColor">

在控制器中:

$scope.changeEmail = function () {
    if ($checkInput.checkEmail($scope.email)) {
        // email input is good
        $scope.emailFormControlColor = 'form-control-success'; // change from error to success
    } else {
        // email input is bad
        if ($scope.emailFormControlColor === 'form-control-success') 
            $scope.emailFormControlColor = 'form-control-error'; // change from success to error
    }
};

服务(这包含在c的控制器参数中):

.service('checkInput', ['$controller', '$window', '$location', function ($controller, $window, $location) {
    return {
        checkEmail: function (email) {
            // <--- I would like to update the ng-class of the focused element here! This would result in me not manually having to write code for each input!
            var regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            return regex.test(email);
        }
    };
}])

上面的代码就是我现在拥有它的方式。如您所见,我手动更改了$ scope.emailFormControlColor。

想象一下,我有三个输入字段:

<input type="text" id="email1" data-ng-model="email1" data-ng-change="changeEmail()" placeholder="your email here" data-ng-class="emailFormControlColor1">
<input type="text" id="email2" data-ng-model="email2" data-ng-change="changeEmail()" placeholder="your email here" data-ng-class="emailFormControlColor2">
<input type="text" id="email3" data-ng-model="email3" data-ng-change="changeEmail()" placeholder="your email here" data-ng-class="emailFormControlColor3">

如何编写我的服务,以便我手动编写以下内容:

$scope.emailFormControlColor1 = 'form-control-success';
$scope.emailFormControlColor2 = 'form-control-success';
$scope.emailFormControlColor3 = 'form-control-success';

我希望我的问题很明确,否则请说,我会更新它!

3 个答案:

答案 0 :(得分:2)

我认为使用指令来解决这个问题更为可取。首先,它被认为是修改控制器或服务中的DOM的反模式。

另一个原因是当您使用指令时,将为您提供使用该指令的DOM元素。这里有一些未经测试的代码可以作为起点使用:

myModule.directive('checkEmail', function() {
  require: 'ngModel',
  link: function(scope, element, attributes, ngModelController) {
    // require that ng-model is used on this element, so you can hook
    // into the Angular validator pipeline ... 
    ngModelController.validators.checkEmail = function(modelValue, viewValue) {
      // now return true or false if viewValue is considered valid
      var regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
      var isValid = regex.test(viewValue);
      // but you also have an opportunity to do your DOM manipulation
      element.toggleClass('form-control-success', isValid);
      element.toggleClass('form-control-error', !isValid);
      return isValid;
    });
  }
});

您可以使用Angular内置的验证系统,而不是像上面那样应用CSS类。您的指令代码与上面相同,除非您不在指令中应用任何CSS类。当指令中的验证代码返回false时,Angular将使该字段无效......您可以使用此事实在HTML中应用CSS:

<form name="myForm">
  <input ng-model="whatever"
         name="email" 
         check-email
         ng-class="{'form-control-success': myForm.email.$valid, 'form-control-error': myForm.email.$invalid}">
</form>

以上内容在字段无效时应用CSS,但您也可以在发生特定验证错误时应用它,在此示例中我们将验证器命名为&#34; checkEmail&#34;,这样也可以:< / p>

<form name="myForm">
  <input ng-model="whatever"
         name="email" 
         check-email
         ng-class="{'form-control-success': !myForm.email.$error.checkEmail, 'form-control-error': myForm.email.$error.checkEmail}">
</form>

答案 1 :(得分:0)

我会创建一个对象,其中包含每封电子邮件所需的所有信息。像这样:

HTML:

<input type="text" id="email0" data-ng-model="emails[0].value" data-ng-change="changeEmail(emails[0])" placeholder="your email here" data-ng-class="emails[0].class">
<input type="text" id="email1" data-ng-model="emails[1].value" data-ng-change="changeEmail(emails[1])" placeholder="your email here" data-ng-class="emails[1].class">
<input type="text" id="email2" data-ng-model="emails[2].value" data-ng-change="changeEmail(emails[2])" placeholder="your email here" data-ng-class="emails[2].class">

JavaScript的:

$scope.emails = [
    { value: '', class: '' },
    { value: '', class: '' },
    { value: '', class: '' },
];

$scope.changeEmail = function (email) {
    if ($checkInput.checkEmail(email)) {
        // email input is good
        email.class = 'form-control-success'; // change from error to success
    } else {
        // email input is bad
        if (email.class === 'form-control-success') {
            email.class = 'form-control-error'; // change from success to error
        }
    }
};

如果合适,您可以使用ng-repeat之类的内容来避免在HTML中复制/粘贴。

答案 2 :(得分:0)

尽管Sunil D.基本上向我指出代码不正确的答案。下面是使其工作的代码。 http://codepen.io/basickarl/pen/MyoZNB

HTML:

<div ng-app="app" ng-controller="ctrl">
  <form name="myForm">
    <input ng-model="name" name="name">
    <input ng-model="email" name="email" check-email>
  </form>
</div>

CSS:

input {
  border: 5px;
  border-style: solid;
  border-color: silver;
}
.input-invalid {
  border-color: red;
}
.input-valid {
  border-color: lime;
}

JS:

var app = angular.module('app', []);
app.controller('ctrl', ['$scope', function($scope) {
  $scope.name = "";
  $scope.email = "";
}]);
app.directive('checkEmail', [function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, el, attr, ctrl) {
      ctrl.$validators.checkEmail = function(modelVal, viewVal) {
        var regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
        var isValid = regex.test(viewVal);
        el.toggleClass('input-valid', isValid);
        el.toggleClass('input-invalid', !isValid);
        return isValid;
      }
    }
  }
}]);