0

I am trying to write an isolated directive that will run regex to validate certain input fields. I want the directive to know what regex to match up on and use based on an attribute on the input.

a sample input would look like this.

<input required tabindex="5" regex-validation regex="validationRegex.zipRegex" ng-model="payment.zip" type="text" />

below is a sample from the directive where it sets up a controller to match on then the directive itself. scope.regex.test logs undefined.

module.controller('Controller', function($scope) {
    $scope.validationRegex = {
        americanExpressRegex: new RegExp(/^(?!3[47]).*$/),
        cvvRegex: new RegExp(/^[0-9]{3,4}$/),
        currencyRegex: new RegExp(/^[$]?\d{0,18}\.?\d{0,2}$/),
        cityRegex: new RegExp(/^[a-zA-Z]+(?:[\s-][a-zA-Z]+)*$/),
        zipRegex: new RegExp(/^[0-9]{5}(?:-[0-9]{4})?$/),
        phoneRegex: new RegExp(/^(\d(\s|\.|\-)?)?\(?\d{3}\)?(\s|\.|\-)?\d{3}(\s|\.|\-)?\d{4}$/),
        /* jshint ignore:start */
        emailRegex: new RegExp("^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?\.)+[A-Za-z0-9](?:[A-Za-z0-9-]*[A-Za-z0-9])?$"),
        /* jshint ignore:end */
        numberRegex: new RegExp(/^\d+$/),
        addressRegex: new RegExp(/^[A-Za-z0-9 \-_\.,]{0,55}$/),
        bankAccountRegex: new RegExp(/^[0-9]{1,17}$/),
        routingNumberRegex: new RegExp(/^((0[0-9])|(1[0-2])|(2[1-9])|(3[0-2])|(6[1-9])|(7[0-2])|80)([0-9]{7})$/)
    };
})
    .directive('regexValidation', [function () {
        return {
        scope: { regex: "=" },
        link: function (scope, element) {
            element.bind('change', function () {
                console.log(scope.regex);
                //grab the element we are working with into a jquery element
                var ele = $(element);

                //grab the element value for multiple future use
                var value = ele.val();

                //if we have a value check with regex
                if (value && !**scope.regex.test**(value)) {
                    ele.parent().addClass("error");
                }
                    //this will set the element back to how it was and check to see if all validation is
                    //complete
                else {
                    ele.parent().removeClass("error");
                }
            });
        }
    };
}]);
  • http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background?rq=1 – m59 Sep 18 '14 at 21:30
  • Did you find my answer helpful? Is there something else you need to know regarding this subject? – m59 Oct 01 '14 at 16:23
  • helpful from a way of thought on approaching things. but was more just looking for why could this directive scope property regex not match up on the proper regex it was told to within the view... I ended up resolving this by pulling the validationRegex object from the controller into the directive and matching on validationRegex property name based on what the regex property of the element provided.... – Corey Michael Cochran Oct 02 '14 at 18:13
  • As my answer explains, you're going to have all kinds of problems because you're working outside of Angular in every way possible. (binding a change listener, pulling a value directly off of the element, modifying classes directly). At that point, Angular is actually fighting you for control of things and is certainly not going to respond to what you want. This is why it is most commonly suggested to stop using jQuery with Angular. It offers little/no help and encourages working against Angular. Does this make sense now? – m59 Oct 03 '14 at 22:02

2 Answers2

2

Get rid of jQuery and never look back. You'll make it a lot further with Angular.

Angular is already working with the changing value of the input and running it through a pipeline. You need to use that pipeline to interact with the value, rather than attaching an event listener.

Check out the ngModelController documentation here.

I explain this process in a lot more detail and with a demo here.

If you're using a recent version of Angular, you'll use a $validator for this. For older versions, you would use a $parser. Rather than adding a class to declare the state, use ngModel's $error state. Here's an example to get you started.

Live demo

.controller('myCtrl', function($scope) {

  $scope.foo = 'abc';
  // in my example, it's always going to be invalid
  $scope.fooValidity = false;

})

.directive('myDirective', function() {

  var directive = {
    scope: {
      isValid: '=myDirective'
    },
    require: 'ngModel',
    link: function($scope, $element, $attrs, $ngModel) {

      // "whatever" is the property which will be assinged on the ngModel $error object
      $ngModel.$validators.whatever = function(val) {
        // write your validation logic here
        // return true or false for valid / invalid
        return $scope.isValid;
      };

    }
  };

  return directive;

})

;

Markup:

<!-- Add the `error` class by using the model's error object -->
<!-- Also note that Anuglar will add a `ng-invalid-whatever` class for you -->
<form name="myForm" ng-class="{error:myForm.fooInput.$error.whatever}">
  <input ng-model="foo" name="fooInput" my-directive="fooValidity">
  <p ng-show="myForm.fooInput.$error.whatever">It's invalid!</p>
</form>
Community
  • 1
  • 1
m59
  • 43,214
  • 14
  • 119
  • 136
-1

Mixing Angularjs and jQuery is not best option. But you can validate your input without jQuery see my working demo here http://plnkr.co/edit/UzQ6DZcKYLk3PCHeEJiv?p=preview

Just pass your model and regular expression to directive and after that test your regular expression on model update

app.directive('regexValidation', [

  function() {
    return {
      scope: {
        regex: "=",
        model: '=ngModel'
      },
      link: function(scope, element, attr) {
        scope.$watch('model', function(newValue, oldValue) {


          if (!newValue|| scope.regex.test(newValue)) {
            element.removeClass("error").addClass('valid');
          } else {
            element.addClass("error").removeClass('valid');
          }
        });
      }
    };
  }
]);
jack wolier
  • 330
  • 1
  • 4
  • 11
  • 1
    Stahp!? Why is everyone posting crazy answers to this?? (the other answer was deleted). – m59 Sep 18 '14 at 23:43
  • I don't mean to be harsh or anything. I see you're new and I commend you for wanting to answer a question and help out. I have already posted an answer here demonstrating the proper solution and linked to the documentation to verify that and another post with much more information about it. This is the second time on this post that an answer using poor practices has been posted *after* I've already posted my answer explaining this. – m59 Sep 19 '14 at 00:13