Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

Need a way to overwrite the email validate logic. #7798

Closed
jswxwxf opened this issue Jun 12, 2014 · 29 comments
Closed

Need a way to overwrite the email validate logic. #7798

jswxwxf opened this issue Jun 12, 2014 · 29 comments

Comments

@jswxwxf
Copy link

jswxwxf commented Jun 12, 2014

Need a way to overwrite the build-in regexp logic that angularjs used to validate the email.
It should be customizable.

@lord2800
Copy link

ng-pattern="/my-regex/"?

@jswxwxf
Copy link
Author

jswxwxf commented Jun 13, 2014

Thanks for answering:)
I know ng-pattern, but it's adding regex check on the email, not replacing the build-in one.

@caitp
Copy link
Contributor

caitp commented Jun 13, 2014

I think you should stop trying to replace the email validation, because this is what email validation is on the web. Does it suck? Well sure, email sucks, but it's what we've got. This is how it works in your browser as well, or at least will be shortly once the last PR for email validation lands.

If you want to enforce that emails are from a specific TLD or something, or even just ensure that they HAVE a TLD, just add a pattern, really. This same line of thinking has been covered at the WHATWG

@jswxwxf
Copy link
Author

jswxwxf commented Jun 19, 2014

Yes, I want to use angularjs's buildin email validator also, but the requirement is always from customers...

@Narretz Narretz added this to the 1.3.0 milestone Jun 23, 2014
@Narretz
Copy link
Contributor

Narretz commented Jun 23, 2014

I agree that something should be done about this, since it will pop up over and over again. Would it conflict with HTML5 constraint validation if the regex angular uses was configurable? Once email & input are merged, it'll also be possible to overwrite the validator. We could mention that or the pattern way in the docs.

@caitp
Copy link
Contributor

caitp commented Jun 23, 2014

the email validator should really match what browsers do --- however we could make it possible to register "extra" validation logic to it.

@rolfyone
Copy link
Contributor

are there examples of 'valid' emails that currently fail validation that lead to this being needed?

is this just the something@some kind of scenario mentioned in #7979 or are there others too that are of specific concern?

@jimmywarting
Copy link
Contributor

one invalid email that passes in angular (but not in the browser) is something@some:aaaa where the port can only be a number

@caitp
Copy link
Contributor

caitp commented Jul 18, 2014

you can't actually include a port number in email hosts, but if we're accepting that then that's a bug to fix in angular. You can extend validation with ng-pattern, however.

@jimmywarting
Copy link
Contributor

you are right @caitp, I mixed it up with url

@caitp
Copy link
Contributor

caitp commented Sep 9, 2014

So... how do we feel about this? I kind of feel like this problem is solved with ng-pattern

@lucassus
Copy link

lucassus commented Sep 9, 2014

What about somehow override default email validation pattern in module configuration block?

@Narretz
Copy link
Contributor

Narretz commented Sep 9, 2014

@caitp
ngPattern doesn't overwrite the email validator, so you need to handle both $error.email and $error.pattern in your submit handler, your error messages etc. Adds a lot of boilerplate.

Overwriting the email validator is another option, but you'll always have to keep up with the core directive. For example, if we support multiple, the custom validator may need to change again.

I think we have two options here:
1 allowing to set the REGEX with ngModelOptions
This removes a lot of boilerplate, but still needs to be set per form
2. Allowing to set the regex in a ngModelProvider / formProvider (could be used in addition to 1.)
Solves this once for each app, might be nice for some people

  1. seems like the better choice, but I don't know if we're overloading ngModelOptions with two much stuff. 2. introduces a new API with little value (except when we allow app wide defaults for ngModelOptions)

@caitp
Copy link
Contributor

caitp commented Sep 9, 2014

ngPattern doesn't overwrite the email validator, so you need to handle both $error.email and $error.pattern in your submit handler, your error messages etc. Adds a lot of boilerplate.

I don't think we actually care --- the email validator validates emails --- that's what it does. What they're asking for is pattern validation, they just want it to use the "email" error name, for no real reason. It's a silly debate, it's completely pointless. The minimal boilerplate that this adds is not significant

@Narretz
Copy link
Contributor

Narretz commented Sep 9, 2014

We should make it easy for people to support their use cases, and the easiest way is customizing the regex.

They are still want to validate email addresses, just stricter than the regex does. Following your logic, we currently don't validate emails or urls (#7816) either, because our regexes are not powerful enough.

@caitp
Copy link
Contributor

caitp commented Sep 9, 2014

I don't think they are actually likely to validate more strictly than the regexp --- people don't want to specify a complete valid URL regexp, because it's a lot of letters --- so more likely they'd be validating something that is not actually an email address, but matches a specific pattern (like /@samsung.com$/ --- which obviously is not a valid email address on its own)

They are still want to validate email addresses, just stricter than the regex does. Following your logic, we currently don't validate emails or urls (#7816) either, because our regexes are not powerful enough.

Well, we do validate emails --- we use essentially the same code for determining a valid email as Chromium, which more or less matches the recommendations from the WHATWG (I believe it's in the forked w3c spec too) and most likely the IETF, although I haven't looked.

URLs are a much harder problem to solve, though. URLs are stupidly complicated, and browsers aren't even totally interoperable when it comes to URLs. You can't really "validate a URL" with a regexp, it's much more complicated than that. It would be hundreds of lines of code to do a better job of it, so unfortunately yeah URL validation is going to leave some things to be desired :(

@Narretz
Copy link
Contributor

Narretz commented Sep 9, 2014

I'm pretty sure all of the issues opened about this have been raised because the regex allows email addresses without a tld. Some even have proposed a different regex that would "solve" the problem. I can't see how this is a special pattern. And if people want a different email regex, why not make it easy for them to change it? I'm not asking to change the current default regex, but if people need something else, they don't care about the IETF etc. I mean today there was another issue that said "the pattern should actually verify only emails with TLDs" How many of these do you want to review and close?

@caitp
Copy link
Contributor

caitp commented Sep 9, 2014

As many as it takes, because I don't believe we should invalidate emails without TLDs --- they are still valid emails (assuming all of the other requirements are met).

A pattern validator is the simple solution for ensuring that there's a TLD, whether it's a specific TLD or just "any". I don't believe this is problematic, because if you really want to verify that someones email address is legit, you're going to have to confirm it, by actually sending an email and receiving a response.

@IgorMinar
Copy link
Contributor

you can override the email regexp by reimplementing the email validator. it should be just a few lines of code:

myModule.directive('myCustomeEmailValidator', function() {
  return {
    require: 'ngModel',
    link: function($scope, $element, $attrs, ngModelController) {
      var MY_EMAIL_REGEXP = /\[email protected]/;
      ngModelController.$validators.email = function(value) {
        return ctrl.$isEmpty(value) || MY_EMAIL_REGEXP.test(value);
      };
    }
  }
});

can we close this issue?

@IgorMinar IgorMinar modified the milestones: Purgatory, 1.3.0 Oct 1, 2014
@Narretz
Copy link
Contributor

Narretz commented Oct 2, 2014

If there's not gonna a configurable way to change the regex we should update the email docs with info about the regex used and forms guide / ngmodel docs how to customize / overwrite validators. I can do that next week.

----- Ursprüngliche Nachricht -----
Von: "Igor Minar" [email protected]
Gesendet: ‎02.‎10.‎2014 00:37
An: "angular/angular.js" [email protected]
Cc: "Narretz" [email protected]
Betreff: Re: [angular.js] Need a way to overwrite the email validate logic.(#7798)

you can override the email regexp by reimplementing the email validator. it should be just a few lines of code:
myModule.directive('myCustomeEmailValidator', function() {
return {
require: 'ngModel',
link: function($scope, $element, $attrs, ngModelController) {
var MY_EMAIL_REGEXP = /\[email protected]/;
ngModelController.$validators.email = function(value) {
return ctrl.$isEmpty(value) || MY_EMAIL_REGEXP.test(value);
};
}
}
});
can we close this issue?

Reply to this email directly or view it on GitHub.=

@IgorMinar
Copy link
Contributor

@Narretz please do!

Narretz added a commit to Narretz/angular.js that referenced this issue Oct 14, 2014
Narretz added a commit to Narretz/angular.js that referenced this issue Oct 17, 2014
@kemins
Copy link

kemins commented Apr 8, 2015

so there is still no way to set TLD as required without writing custom directive or pattern.

@jswxwxf
Copy link
Author

jswxwxf commented Apr 8, 2015

And if the custom directive or pattern has different rule, then both will be applied to validate the email.
It's actually not overwriting the exist email pattern, it's adding a new validation rule.

@Narretz
Copy link
Contributor

Narretz commented Apr 8, 2015

There's an example that shows how to overwrite the email validator: https://docs.angularjs.org/guide/forms#modifying-built-in-validators

@ExplodingCabbage
Copy link

This is still an imperfect solution; if I want custom email validation that is stricter-than-spec (and, like everybody including Google, I do), then I want to apply those standards consistently across every email input in my application, without the risk that somebody will forget to add whatever customEmailValidation directive I create to one of them. This is why people are calling for the ability to customise the type=email validation, which still isn't possible.

@gkalpak
Copy link
Member

gkalpak commented Apr 14, 2015

@ExplodingCabbage: You can still apply the custom validation to every input[type="email"] with the appropriate directive. E.g.:

.directive('input', function () {
  ...
  return {
    ...
    restrict: 'E',
    link: function (scope, elem, attrs) {
      if (attrs.type !== 'email') return;

      ...
    }

@ExplodingCabbage
Copy link

@gkalpak oh, wow, I'd always assumed that all directives had to have unique names. Thanks for very usefully pointing out my error!

@fttx
Copy link

fttx commented Feb 14, 2016

The example in the documentation works pretty well but you should consider to add an easiest way to override the regex, it may be useful to all those who want to take advantage of the custom keyboard provided thanks to the type attribute but at the same time define a custom validation pattern.
A practical example could be an ipv4/dns field, where the most appropriate input type is url.

@gkalpak
Copy link
Member

gkalpak commented Feb 16, 2016

@fttx, you can already use ngPattern (which is super easy to setup) on a per-case basis.
And even if you want to overwrite the validator globally (i.e. for all input[type="email"] fields), a really short directive is all it takes:

.directive('input', function() {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function(scope, elem, attrs, ctrl) {
      if (ctrl && ctrl.$validators.email) {
        ctrl.$validators.email = function(value) {
          return ctrl.$isEmpty(value) || /* YOUR REGEXP */.test(value);
        };
      }
    }
  };
});

Even if we provided a way to overwrite it globally per app, it wouldn't be much simpler than that (there would be some provider that would have to inject during the config phase and call some function that sets the e-mail RegExp etc).

Considering it is not too common a usecase and there are already adequate ways available for handling it, I'd say we shouldn't add more bloat to core.
Note you can always provide this fuctionality and a separate module and just add it as a dependency to your app.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests