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

Email validation not working with Chrome autofill #1072

Closed
kylefinley opened this issue Jun 18, 2012 · 13 comments
Closed

Email validation not working with Chrome autofill #1072

kylefinley opened this issue Jun 18, 2012 · 13 comments

Comments

@kylefinley
Copy link

As discussed here:
https://groups.google.com/forum/?fromgroups#!topic/angular/GQVX5F3v7Xk

When using Chrome autofill angular is not reevaluating the email address after the fill, therefore, it believes it to be invalid.

Here's a jsfiddle demonstrating the issue:
http://jsfiddle.net/kylefinley/DuM6D/14/

There's a screen shot in the linked thread.

This issues appears in the following Chromium browsers:

Iron Version 19.0.1100.0 (139545)
Chromium Version 21.0.1180.0 (142701)
Chrome Version 19 - 20.0.1132.34 beta

Please let me know if you are not able to reproduce this.

Thank you,

Kyle

@IgorMinar
Copy link
Contributor

I can't reproduce this on MacOS 10.7 with Chrome 20.0.1132.34 beta or 21.0.1179.0 canary.

If anything this is a browser bug - the browser doesn't trigger the "input" event when the autofill is committed by selecting the email address from the list and hitting enter or clicking on it.

I'm going to close this issue for now, but if you are still affected by it, please do let us know. You could also try to test the latest canary version and see if you can reproduce it there.

If we do need to follow up on this issue, it will most likely be by refiling this as a Chrome bug, but for that we need to be able to reproduce it.

@kylefinley
Copy link
Author

I figured out what is going on. The reason that it's difficult to reproduce is because there are two ways that Chrome will populate fields.

  1. With tab completions - this uses the name of the field to bring up a list of options.
  2. Using Autofill. When autofill is used the background color of the input will be changed to yellow. Also, the words "Chrome Autofill settings" appears at the bottom of the drop down list.

In this case Autofill is creating the problem. Autofill only populates the form when the following two conditions are met.

  1. The user has saved information in their autofill profile. ( chrome://chrome/settings/autofill )
  2. The form has a method="POST" attribute.

So to reproduce:

  1. Visit: chrome://chrome/settings/autofill
  2. Click Add new street address...
  3. Fill in form including email
  4. Revisit http://jsfiddle.net/kylefinley/DuM6D/14/

When using autofill you should then see the issue.

This simplest solution is to remove the method="POST" from the form, which is the documented way to use Angular forms. The problem with this approach is it disregards User's Autofill information. If you still can reproduce this or you deem the work around acceptable, please feel free to leave the issue close. Now that I have a way to circumvent autofills behavior, I'm content.

@robrbecker
Copy link

I can recreate this issue on Chrome Stable 19 and Angular 1.0 and 1.0.1. I'm doing exactly what kylefinley was doing. The form method is POST and I'd like to let people use autofill if they have it. I'd settle for a way to trigger an angular update manually when they click "continue" button.

After some trial and error and re-reading Igor's post I discovered I can simply do this to get the browser to fire input events for things that may have been filled in by autofill but haven't updated.
example: $('#myform input,myform select').trigger('input');

@robrbecker
Copy link

(Edit to fix typo)
If you have a submit or click handler for the form submission you can trigger the input event on all your inputs so that angular will pick up the changes by autofill.

Fire input event on all inputs:
$('#myform input,#myform select').each(function() { $(this).trigger('input'); });

Or you can try firing an input event when other events happen like change or blur:
$('#myform input,#myform select').on('change blur', function() { $(this).trigger('input'); });

PSA: This probably has performance implications and over triggers events.

@kylefinley
Copy link
Author

Thank you @robrbecker for investigating this. It's good to have an alternative that works with Chrome's Autofill.

@johannesjo
Copy link

@robrbecker: Thanks for sharing, but I'm running into the problem that I get

Error: $apply already in progress

It works for the automatically populated fields, but deletes the data for all others. Very strange. Maybe I'm doing something wrong, but I would definitely suggest, to not use this fix for production builds.

@robrbecker
Copy link

@johannesjo Make sure you register these event listeners only once at dom ready. For instance this is what I'm doing.

var app = angular.module('app',[]);
app.run(function() {
// Trigger input event on change to fix auto-complete
$('input, select').on('change',function() { $(this).trigger('input'); });
});

Do your own testing on your own app of course.

@malixsys
Copy link
Contributor

This works for me:

function MyController($scope) {
  setTimeout(function() {
    $scope.$apply(function () {
      $('input[ng-model]').trigger('change');
    });
  }, 250);
}

As long as jQuery is loaded before Angular, of course!!

You can also use $timeout...

@ghost
Copy link

ghost commented Jul 11, 2013

I'm getting this in Chrome 28 now even without method="POST".

@katalin2003
Copy link

I came here searching for a solution as i have the same problem.
Removing method="POST" is not an option for me unfortunately.

@malixsys
Copy link
Contributor

malixsys commented Nov 6, 2013

I now use the following directive:

    var ValidSubmit = ['$parse','$timeout', function ($parse, $timeout) {
        return {
            require: '^form',
            link: function(scope, element, attrs, form) {
                        form.$submitted = false;
                        var fn = $parse(attrs.validSubmit);
                        element.on('submit', function(event) {
                            var inputs = element.find("*[ng-model]")
                            for(var i=0; i < inputs.length; i++) {
                                var ele = inputs.eq(i);
                                var field = form[inputs[i].name];
                                if(field != void 0) {
                                    if(inputs[i].type == "checkbox" || inputs[i].type == "hidden") {
                                        field.$setViewValue(field.$viewValue);
                                    } else {
                                        field.$setViewValue(ele.val());
                                    }
                                }
                            }
                            scope.$apply(function() {
                                element.addClass('ng-submitted');
                                form.$submitted = true;
                                if(form.$valid) {
                                    fn(scope, {$event:event});
                                }
                            });
                        });
                    }
        }

    }]
    app.directive('validSubmit', ValidSubmit);

@jaichandra
Copy link

Hi malixsys,

Can you please also tell how you are using that directive? I tried adding it to the

element and it does bind the model but only after I click submit button. and then, I have to click submit again to submit the form. can this work 'onchange' of the input field value?

Thanks

@malixsys
Copy link
Contributor

Check
https://github.com/malixsys/matryoshka/blob/master/app/client/app/anonymous/views/state_login.html et. al.
The validation appears only on submit...

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

No branches or pull requests

7 participants