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

input type=email doesn't work in IE9 #4546

Closed
mb666 opened this issue Oct 20, 2013 · 21 comments
Closed

input type=email doesn't work in IE9 #4546

mb666 opened this issue Oct 20, 2013 · 21 comments

Comments

@mb666
Copy link

mb666 commented Oct 20, 2013

Hi, I'm trying to get my app to work for IE9.

I'm actually using IE10 with Browser Mode set to IE9 and Document Mode set to IE9 standards.

On the input [email] docs page (http://docs.angularjs.org/api/ng.directive:input.email) in version v1.2.0-08f376f it seems like email validation does not work in IE9:
image

Notice how the value of the textbox is '123' and myForm.$error.email = false

Is this a bug? Do you plan to fix it?

Thanks

@caitp
Copy link
Contributor

caitp commented Oct 20, 2013

This may be another ValidityState-related issue, where the ValidityState of an input is ignored, and the value seen in the DOM is the empty string (despite the innerText of the input, which is actually separate from its value).

However to my knowledge, IE does not support ValidityState until IE10. If you could investigate the DOM properties of the Input element in IE9 to see what you can find, that would be awesome.

I've tried to solve this for webkit/blink input[type=number] via #4293, it doesn't work perfectly -- but mostly works well. Perhaps a similar strategy would work for input[type=email] --- I've structured my patch so that it should be easy to plug in to other input types if needed.

edit: I guess if required===true, then it must be a different issue. But still, see what you can find in the DOM, I'd be very curious

@mb666
Copy link
Author

mb666 commented Oct 21, 2013

In IE10 the validation seems to work fine.

Shall I just serialise the input element to json and paste it here?

Sent from my mobile phone

On 21 Oct 2013, at 00:52, Caitlin Potter notifications@github.com wrote:

This may be another ValidityState-related issue, where the ValidityState of an input is ignored, and the value seen in the DOM is the empty string (despite the innerText of the input, which is actually separate from its value).

However to my knowledge, IE does not support ValidityState until IE10. If you could investigate the DOM properties of the Input element in IE9 to see what you can find, that would be awesome.


Reply to this email directly or view it on GitHub.

@caitp
Copy link
Contributor

caitp commented Oct 21, 2013

It might be helpful, and I do not have access to IE10 to test myself.

@mb666
Copy link
Author

mb666 commented Oct 22, 2013

Page:
http://docs.angularjs.org/#!/api/ng.directive:input.email
AngularJS - v1.2.0-b9557b0

__Browser: __
Internet Explorer 10 in browser mode IE9 and document mode IE9 standards
(in other words IE 10 is emulating IE 9)

el = document.querySelectorAll('input[ng-model=text]')[0]
for(var prop in el) { console.log(prop, '=', el[prop]); }

ng-1382474647010=679
align=
border=
hspace=0
vspace=0
accept=
alt=
checked=false
defaultChecked=false
defaultValue=
form=[object HTMLFormElement]
height=0
indeterminate=false
maxLength=2147483647
name=input
readOnly=false
selectionEnd=0
selectionStart=0
size=20
src=
type=text
useMap=
value=123123
width=0
dataFld=
dataFormatAs=
dataSrc=
complete=false
status=false
dynsrc=
loop=1
lowsrc=
start=fileopen
vrml=
select=
function select() {
[native code]
}

setSelectionRange=
function setSelectionRange() {
[native code]
}

createTextRange=
function createTextRange() {
[native code]
}

currentStyle=[object MSCurrentStyleCSSProperties]
runtimeStyle=[object MSStyleCSSProperties]
accessKey=
className=ng-valid ng-valid-required ng-dirty
contentEditable=inherit
dir=
disabled=false
id=
innerHTML=
isContentEditable=true
lang=
offsetHeight=28
offsetLeft=781
offsetParent=[object HTMLBodyElement]
offsetTop=1739
offsetWidth=220
onabort=null
onblur=null
oncanplay=null
oncanplaythrough=null
onchange=null
onclick=null
oncontextmenu=null
ondblclick=null
ondrag=null
ondragend=null
ondragenter=null
ondragleave=null
ondragover=null
ondragstart=null
ondrop=null
ondurationchange=null
onemptied=null
onended=null
onerror=null
onfocus=null
oninput=null
onkeydown=null
onkeypress=null
onkeyup=null
onload=null
onloadeddata=null
onloadedmetadata=null
onloadstart=null
onmousedown=null
onmousemove=null
onmouseout=null
onmouseover=null
onmouseup=null
onmousewheel=null
onpause=null
onplay=null
onplaying=null
onprogress=null
onratechange=null
onreadystatechange=null
onreset=null
onscroll=null
onseeked=null
onseeking=null
onselect=null
onstalled=null
onsubmit=null
onsuspend=null
ontimeupdate=null
onvolumechange=null
onwaiting=null
outerHTML=
style=[object MSStyleCSSProperties]
tabIndex=0
title=
all=[object HTMLCollection]
behaviorUrns=[object MSBehaviorUrnsCollection]
canHaveChildren=true
canHaveHTML=false
children=[object HTMLCollection]
document=[object Document]
filters=[object]
hideFocus=false
innerText=
isDisabled=false
isMultiLine=false
isTextEdit=true
language=
onactivate=null
onafterupdate=null
onbeforeactivate=null
onbeforecopy=null
onbeforecut=null
onbeforedeactivate=null
onbeforeeditfocus=null
onbeforepaste=null
onbeforeupdate=null
oncellchange=null
oncontrolselect=null
oncopy=null
oncut=null
ondataavailable=null
ondatasetchanged=null
ondatasetcomplete=null
ondeactivate=null
onerrorupdate=null
onfilterchange=null
onfocusin=null
onfocusout=null
onhelp=null
onlayoutcomplete=null
onlosecapture=null
onmouseenter=null
onmouseleave=null
onmove=null
onmoveend=null
onmovestart=null
onpaste=null
onpropertychange=null
onresize=null
onresizeend=null
onresizestart=null
onrowenter=null
onrowexit=null
onrowsdelete=null
onrowsinserted=null
onselectstart=null
outerText=
parentElement=[object HTMLFormElement]
parentTextEdit=[object HTMLBodyElement]
readyState=complete
recordNumber=null
scopeName=HTML
sourceIndex=1426
tagUrn=
uniqueID=ms__id19
uniqueNumber=19
blur=
function blur() {
[native code]
}

click=
function click() {
[native code]
}

focus=
function focus() {
[native code]
}

getElementsByClassName=
function getElementsByClassName() {
[native code]
}

insertAdjacentHTML=
function insertAdjacentHTML() {
[native code]
}

scrollIntoView=
function scrollIntoView() {
[native code]
}

componentFromPoint=
function componentFromPoint() {
[native code]
}

doScroll=
function doScroll() {
[native code]
}

attachEvent=
function attachEvent() {
[native code]
}

detachEvent=
function detachEvent() {
[native code]
}

addBehavior=
function addBehavior() {
[native code]
}

addFilter=
function addFilter() {
[native code]
}

applyElement=
function applyElement() {
[native code]
}

clearAttributes=
function clearAttributes() {
[native code]
}

contains=
function contains() {
[native code]
}

dragDrop=
function dragDrop() {
[native code]
}

getAdjacentText=
function getAdjacentText() {
[native code]
}

insertAdjacentElement=
function insertAdjacentElement() {
[native code]
}

insertAdjacentText=
function insertAdjacentText() {
[native code]
}

mergeAttributes=
function mergeAttributes() {
[native code]
}

releaseCapture=
function releaseCapture() {
[native code]
}

removeBehavior=
function removeBehavior() {
[native code]
}

removeFilter=
function removeFilter() {
[native code]
}

replaceAdjacentText=
function replaceAdjacentText() {
[native code]
}

setActive=
function setActive() {
[native code]
}

setCapture=
function setCapture() {
[native code]
}

createControlRange=
function createControlRange() {
[native code]
}

removeNode=
function removeNode() {
[native code]
}

replaceNode=
function replaceNode() {
[native code]
}

swapNode=
function swapNode() {
[native code]
}

clientHeight=26
clientLeft=1
clientTop=1
clientWidth=218
scrollHeight=26
scrollLeft=0
scrollTop=0
scrollWidth=218
tagName=INPUT
childElementCount=0
firstElementChild=null
lastElementChild=null
nextElementSibling=[object HTMLSpanElement]
previousElementSibling=null
getAttribute=
function getAttribute() {
[native code]
}

getAttributeNS=
function getAttributeNS() {
[native code]
}

getAttributeNode=
function getAttributeNode() {
[native code]
}

getAttributeNodeNS=
function getAttributeNodeNS() {
[native code]
}

getBoundingClientRect=
function getBoundingClientRect() {
[native code]
}

getClientRects=
function getClientRects() {
[native code]
}

getElementsByTagName=
function getElementsByTagName() {
[native code]
}

getElementsByTagNameNS=
function getElementsByTagNameNS() {
[native code]
}

hasAttribute=
function hasAttribute() {
[native code]
}

hasAttributeNS=
function hasAttributeNS() {
[native code]
}

removeAttribute=
function removeAttribute() {
[native code]
}

removeAttributeNS=
function removeAttributeNS() {
[native code]
}

removeAttributeNode=
function removeAttributeNode() {
[native code]
}

setAttribute=
function setAttribute() {
[native code]
}

setAttributeNS=
function setAttributeNS() {
[native code]
}

setAttributeNode=
function setAttributeNode() {
[native code]
}

setAttributeNodeNS=
function setAttributeNodeNS() {
[native code]
}

fireEvent=
function fireEvent() {
[native code]
}

msMatchesSelector=
function msMatchesSelector() {
[native code]
}

querySelector=
function querySelector() {
[native code]
}

querySelectorAll=
function querySelectorAll() {
[native code]
}

attributes=[object NamedNodeMap]
childNodes=[object NodeList]
firstChild=null
lastChild=null
localName=input
namespaceURI=http://www.w3.org/1999/xhtml
nextSibling=[object Text]
nodeName=INPUT
nodeType=1
nodeValue=null
ownerDocument=[object Document]
parentNode=[object HTMLFormElement]
prefix=null
previousSibling=[object Text]
textContent=
addEventListener=
function addEventListener() {
[native code]
}

dispatchEvent=
function dispatchEvent() {
[native code]
}

removeEventListener=
function removeEventListener() {
[native code]
}

appendChild=
function appendChild() {
[native code]
}

cloneNode=
function cloneNode() {
[native code]
}

compareDocumentPosition=
function compareDocumentPosition() {
[native code]
}

hasAttributes=
function hasAttributes() {
[native code]
}

hasChildNodes=
function hasChildNodes() {
[native code]
}

insertBefore=
function insertBefore() {
[native code]
}

isDefaultNamespace=
function isDefaultNamespace() {
[native code]
}

isEqualNode=
function isEqualNode() {
[native code]
}

isSameNode=
function isSameNode() {
[native code]
}

isSupported=
function isSupported() {
[native code]
}

lookupNamespaceURI=
function lookupNamespaceURI() {
[native code]
}

lookupPrefix=
function lookupPrefix() {
[native code]
}

normalize=
function normalize() {
[native code]
}

removeChild=
function removeChild() {
[native code]
}

replaceChild=
function replaceChild() {
[native code]
}

ATTRIBUTE_NODE=2
CDATA_SECTION_NODE=4
COMMENT_NODE=8
DOCUMENT_FRAGMENT_NODE=11
DOCUMENT_NODE=9
DOCUMENT_POSITION_CONTAINED_BY=16
DOCUMENT_POSITION_CONTAINS=8
DOCUMENT_POSITION_DISCONNECTED=1
DOCUMENT_POSITION_FOLLOWING=4
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC=32
DOCUMENT_POSITION_PRECEDING=2
DOCUMENT_TYPE_NODE=10
ELEMENT_NODE=1
ENTITY_NODE=6
ENTITY_REFERENCE_NODE=5
NOTATION_NODE=12
PROCESSING_INSTRUCTION_NODE=7
TEXT_NODE=3

image

Required validation works fine.
I think that IE9 doesn't support input[type=email], my understanding is that AngularJS renders input as type=text and should apply validation internally.
Let me know if you need anything else.

@caitp
Copy link
Contributor

caitp commented Oct 22, 2013

Browsers (at least every browser that I am aware of) internally turns it into input[type=text] if the input type isn't supported.

I'm not seeing validity in your stuff at all, which is curious because IE10 claims to support it (http://msdn.microsoft.com/en-us/library/ie/hh773263(v=vs.85).aspx). The angular docs are using IE=edge content settings, so I don't see any reason why you wouldn't have the IE10 features unless you're manually overriding the engine.

Alternatively, if you're using ChromeFrame, then this could be a different issue (but that wouldn't explain why the ValidityState isn't visible)

@mb666
Copy link
Author

mb666 commented Oct 22, 2013

The browser I'm using is IE 10 however in developer tools I'm changing Browser Mode to IE9 and Document Mode to IE9. I believe that makes the browser to behave like IE9. I don't have the access to original IE9,

This link (http://msdn.microsoft.com/en-us/library/ie/hh773263(v=vs.85).aspx) doesn't explicitly mention IE9 therefore I'm not sure whether it's safe to assume anything about IE9.

@caitp
Copy link
Contributor

caitp commented Oct 22, 2013

Yes, IE9 does not include ValidityState. It may still return the empty string in the case of invalid email inputs without exposing the ValidityState. http://www.quirksmode.org/html5/inputs.html states that IE9 does not support input[type="email"] at all, however. To my knowledge, the email regex is well tested and working, and the test suite is running on IE8, 9 and 10, so... I'm not sure what the issue is exactly, since I don't have a browser to test with.

@mb666
Copy link
Author

mb666 commented Nov 2, 2013

Thanks for your answer Caitlin. Does anyone else has IE browser and could
confirm the issue?

On 22 October 2013 22:29, Caitlin Potter notifications@github.com wrote:

Yes, IE9 does not include ValidityState. It may still return the empty
string in the case of invalid email inputs without exposing the
ValidityState. http://www.quirksmode.org/html5/inputs.html states that
IE9 does not support input[type="email"] at all, however. To my
knowledge, the email regex is well tested and working, and the test suite
is running on IE8, 9 and 10, so... I'm not sure what the issue is exactly,
since I don't have a browser to test with.


Reply to this email directly or view it on GitHubhttps://github.com//issues/4546#issuecomment-26852260
.

@jpgauthier
Copy link

I tried it on IE 9.0.21, can't reproduce the issue
image

@wlingke
Copy link

wlingke commented Dec 7, 2013

I confirmed this issue. IE 8 and 9 do not support type="email" thus it doesn't get picked up. We wrote a directive to handle this action. Here's the code that would go inside the linking function. Don't forget to require ngModel and include ctrl as the fourth variable in the linking function.

var ie8n9 = true //set this where you test for this browser
if (ie8n9) {
    var emailReg = new RegExp(/^(("[\w-\s]+")|([\w-]+(?:\.[\w-]+)*)|("[\w-\s]+")([\w-]+(?:\.[\w-]+)*))(@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)$)|(@\[?((25[0-5]\.|2[0-4][0-9]\.|1[0-9]{2}\.|[0-9]{1,2}\.))((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\.){2}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[0-9]{1,2})\]?$)/i);
    ctrl.$parsers.unshift(function (viewValue) {
        if (emailReg.test(viewValue) || (!emailReg.test(viewValue) && ctrl.$error.required) ) {
            //it is valid or if it's invalid but required is not satisfied we only want to show required error
                ctrl.$setValidity('email', true);
                return viewValue;
        } else {
            //it is invalid
            ctrl.$setValidity('email', false);
            return undefined;
        }
    })
}

@caitp
Copy link
Contributor

caitp commented Dec 7, 2013

doesn't input[type=email] already have validation functions in input.js?

function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) {

Maybe I'm confused but I'm not seeing what your custom directive does that that doesn't

@wlingke
Copy link

wlingke commented Dec 7, 2013

@caitp Doh! Totally forgot about that. Use that!

@mb666
Copy link
Author

mb666 commented Dec 17, 2013

I'm using Internet Explorer 11 (version 11.0.9600.16476) with developer tools IE 9 emulation (Document mode 9, User agent string Internet Explorer 9).

Url is http://code.angularjs.org/1.2.5/docs/#!/api/ng.directive:input.email

When I enter the string '123' into email box I get:
text = 123
myForm.input.$valid = true
myForm.input.$error = {"required":false}
myForm.$valid = true
myForm.$error.required = false
myForm.$error.email = false

This is clearly wrong.
I will try to get hold of real Internet Explorer version 9 instead of latest version with IE and emulation.
But the input[type=email] validation should work even if I'm using emulation.
Is angular not detecting the browser correctly when in emulation mode?

@caitp
Copy link
Contributor

caitp commented Dec 18, 2013

@mb666, what sort of results do you get running this? Interestingly I'm not even getting the empty string on Chrome, which is what it would typically give, hmm, guess it only does that on badInput: true. hmm

I don't think emulation modes are actually supported, though.

@mb666
Copy link
Author

mb666 commented Dec 18, 2013

@caitp I've run http://plnkr.co/edit/vV1TnRe7XHBfzpPnzT9U?p=preview on Internet Explorer 11 (version 11.0.9600.16476) with following results :

  • no emulation: text = '123' result is {}
  • IE 10 emulation: text = '123' result is {}
  • IE 9 emulation: plunkr not starting. I get errors in the console:
    • 10 $digest() iterations reached. Aborting!
      Watchers fired in the last 5 iterations: [["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 7; oldVal: 6"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 8; oldVal: 7"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 9; oldVal: 8"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 10; oldVal: 9"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 11; oldVal: 10"]]
    • SCRIPT5022: 10 $digest() iterations reached. Aborting!
      Watchers fired in the last 5 iterations: [["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 7; oldVal: 6"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 8; oldVal: 7"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 9; oldVal: 8"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 10; oldVal: 9"],["fn: function(){var e=r.url(),t=l.$$replace;return h&&e==l.absUrl()||(h++,i.$evalAsync(function(){i.$broadcast("$locationChangeStart",l.absUrl(),e).defaultPrevented?l.$$parse(e):(r.url(l.absUrl(),t),a(e))})),l.$$replace=!1,h}; newVal: 11; oldVal: 10"]]
      File: editor-0.7.10.js, Line: 2, Column: 13261

In Chrome I'm getting this:
123
{
"valid": false,
"customError": false,
"badInput": false,
"stepMismatch": false,
"rangeOverflow": false,
"rangeUnderflow": false,
"tooLong": false,
"patternMismatch": false,
"typeMismatch": true,
"valueMissing": false
}

@caitp
Copy link
Contributor

caitp commented Dec 18, 2013

the IE9 error you're getting seems to be an issue with plnkr itself, since that test is not an angular app :p that's unfortunate. You could try shoving it into a jsfiddle and see how it works there, but I wouldn't be too worried about it, since my initial theory that it was browser constraints validation causing the issue appears to be false.

Anyways, to my knowledge there's nothing in the emailInputType function which cares what browser you're using. It tests if the value is not empty, and matches the email regexp. So short of that, it shouldn't be marked as valid.

If you can investigate this (I would myself, but I don't have a windows machine to test with), perhaps you can turn up a reason why.

@mb666
Copy link
Author

mb666 commented Dec 18, 2013

@caitp I saved the html from your plnkr as local html file. Here is the bevaviour I get with Internet Explorer 11 (version 11.0.9600.16476):

  • no emulation: 123: {}
  • IE 10 emulation: 123: {}
  • IE 9 emulation: 123:
  • IE 8 emulation: 123:
  • IE 7 emulation: 123:

So if the browser version is below 10 I get no empty object.
Is this behaviour expected?

@caitp
Copy link
Contributor

caitp commented Dec 18, 2013

It just means they don't have the ValidityState stuff, it's no big deal, the issue is unrelated to any of that. It was a mistaken hunch as I said already ;)

To my knowledge, there's no reason why emailInputType should fail to work with IE9 emulation, but I guess anythings possible. If you can spot why, send a patch to fix it! But, again, emulated browsers are not really supported even by MS.

@IgorMinar
Copy link
Contributor

can someone please confirm that the issue is present only for emulated IE9 and not for real IE9?

@CaptainJiNX
Copy link

Yes, I just checked in a real IE9, and it seems to work just fine. Emulated IE9 from IE10 does not validate at all for me...

@btford btford removed the gh: issue label Aug 20, 2014
@lgalfaso
Copy link
Contributor

lgalfaso commented Jan 6, 2015

with #4546 (comment), I think there is nothing else to talk about. If someone has this issue with a real IE9, please post here

@lgalfaso lgalfaso closed this as completed Jan 6, 2015
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

8 participants