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

fix(input): don't dirty model when input event triggered due to placeholder change #5960

Closed
wants to merge 1 commit into from

Conversation

caitp
Copy link
Contributor

@caitp caitp commented Jan 23, 2014

Certain versions of IE inexplicably trigger an input event in response to a placeholder being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if the element is not attached to the document, and the event triggers asynchronously so it is not possible to accomplish this without deferring DOM compilation and slowing down load times.

Closes #2614
Closes #5960


This that could theoretically go wrong:

  • If a value change and a placeholder change both occur and emit a single coalesced event (rather than two independent events), this may lead to a model occasionally not being updated. I imagine this would be pretty rare in practice.
  • If a test for lastValue === value is added to the exit condition, then the same issue above still potentially happens when an empty string becomes an invalid string and constraint validation gives us an empty string.

There are probably a few more holes in this, unfortunately, which is why it would be better if MS would hotfix the affected browsers. But it's not breaking any tests and if it doesn't break any apps which dogfood it then that's probably fine.

caitp added a commit to caitp/angular.js that referenced this pull request Jan 23, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
@@ -509,6 +509,43 @@ describe('input', function() {
});
}


it('should not dirty the model on an input event in response to a placeholder change', inject(function($document) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test doesn't really work without the async junk, sorry about that :(

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. I wonder whether the benefit of actually testing against the real behaviour in IE10 is worth the async stuff. Perhaps we should just mock out the IE bits and isolate the code you wrote?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll see if it's mock-able

@petebacondarwin
Copy link
Contributor

Do we know exactly what versions of IE exhibit this behaviour?

@caitp
Copy link
Contributor Author

caitp commented Jan 23, 2014

the original issue and some stackoverflow posts report IE10 and a few cases IE11, with unknown emulation modes (but it definitely affects IE10 standards mode)

https://travis-ci.org/angular/angular.js/jobs/17502175 this build doesn't have the fix, just the test, so you can see it fail a few times

@petebacondarwin
Copy link
Contributor

This is quite nasty. I wonder if it is fixable with a polyfill for placeholder instead. Then we can offer that as a work around rather than hacking AngularJS?
Here is a list of such polyfills. https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-browser-Polyfills#web-forms--input-placeholder

What do you think?

@caitp
Copy link
Contributor Author

caitp commented Jan 23, 2014

I think it's worth a shot, but I don't think there's any guarantee it would work. I'll try it out on saucelabs real quick

Actually most of these shims look like they're just adding placeholder rendering to browsers which don't support it natively, so I'm not super convinced these would fix the issue

@petebacondarwin
Copy link
Contributor

So these polyfills tend to remove the placeholder attribute altogether and then simulate it instead.

@petebacondarwin
Copy link
Contributor

OK, so I guess that apart from fine tuning the conditions of the if I think that this approach looks fine.

@caitp
Copy link
Contributor Author

caitp commented Jan 23, 2014

Just tested all of those polyfills with stock angular 1.2.9 on saucelabs IE10 http://plnkr.co/edit/PWwP3OZTtcp7VUEDHLcq?p=preview, none of them solve the issue. So maybe the if conditions can be tuned up a bit.

On the other hand maybe it's not totally worth fixing it, I dunno. I'll see if I can clean it up a bit, though

caitp added a commit to caitp/angular.js that referenced this pull request Jan 23, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
caitp added a commit to caitp/angular.js that referenced this pull request Jan 23, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
caitp added a commit to caitp/angular.js that referenced this pull request Jan 23, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
@@ -509,6 +509,28 @@ describe('input', function() {
});
}


it('should not dirty the model on an input event in response to a placeholder change', inject(function($sniffer) {
if (msie && $sniffer.hasEvent('input')) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lastly, could remove the msie check from both the test and the code, which is probably okay but I'm not positive

caitp added a commit to caitp/angular.js that referenced this pull request Jan 24, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes angular#2614
Closes angular#5960
// Some versions of MSIE emit an 'input' event when the placeholder attribute/property
// change. This hack prevents an otherwise pristine field from being dirtied on IE
// browsers.
if (msie && (event || noevent).type === 'input' && element[0].placeholder !== placeholder) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make note of affected IE versions here

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you change this to msie < 11 and test it on IE11?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're running Angular 1.0.8, and only had the placeholder problem in IE10 (IE v10.0.9200.16899 on Windows 8). We added the changes to the textInputType function, and it solved the problem.

@IgorMinar
Copy link
Contributor

otherwise this looks good

@caitp caitp closed this in ff428e7 Apr 18, 2014
caitp added a commit that referenced this pull request Apr 18, 2014
…holder change

Certain versions of IE inexplicably trigger an input event in response to a placeholder
being set.

It is not possible to sniff for this behaviour nicely as the event is not triggered if
the element is not attached to the document, and the event triggers asynchronously so
it is not possible to accomplish this without deferring DOM compilation and slowing down
load times.

Closes #2614
Closes #5960
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
4 participants