How to make your AngularJS app work in IE 8

Written by Andreas Marek (@andimarek).

We (the team I work in) are developing an AngularJS application for the last several months. Most of our customers are still using IE 8, so we need to support that browser.

Our app is using AngularJS 1.1.5 and jQuery 1.x.

A few weeks ago it was time to make our app work in IE 8. A good starting point is the official Angular IE guide. Nevertheless the promoted solutions didn’t completely work for us.

We had to deal with three main problems and some „normal“ IE problems regarding html and css. I will discuss the main problems, the minor once are well documented all over the internet (and very app specific) and were easily fixed by a little research and trial and error.

Problem 1: Ajax caching

All browsers don’t cache Ajax requests, except IE. Normally this isn’t what you want. If you google about this problem, you will get a handful suggestions how to solve it.

We decided to set the http response header ‚cache-control‘:’no-cache‘ for every http Ajax response. That’s all what you need for IE 8,9,10. And of course it doesn’t hurt Chrome/Firefox, because that’s their default behaviour.

You don’t need ‚pragma‘:’no-cache‘ or any other additionally headers as sometimes suggested.

Problem 2: Custom html elements

(Important: Because our app has jQuery 1.x included Angular uses jQuery instead of jqLite. If you are not including jQuery you might experience other IE behaviour as described here.)

This was our biggest problem we had to overcome. The core problem is well known: IE 8 doesn’t like unknown html elements, i.e. article (a html5 element) or custom directives used as element. Our app wouldn’t even start in IE 8: Just some JS errors without stacktrace. How your app reacts when you include unknown elements highly depends on your app and where your the elements are in the DOM.

Our app uses ng-view and around 10 custom elements. One way to solve our problem would have been not to use custom elements at all: Just declare your directive as attribute and replace all html5 elements (with div for example) and everything works.

We wanted to avoid any huge refactoring just for IE 8, so we tried to fix our app with the official guide and other known work arounds for that problem: See html5shiv or modernizr.

Nothing of this worked, because of the dynamic DOM manipulation done by Angular in conjunction with jQuery. (If your app just has static content, including html5shiv will work fine.)

Solution: Extending jQuery’s internal list of html elements

After some research and experimentation we found a solution, that is working very good. Since 1.7 some support for html5 in IE 8 is already included (see Ticket#6485). It’s not perfect but for our problem it was nearly enough.

The only missing piece were our own elements. jQuery has a internal list of html5 element names to support them in old IEs. So we added our own elements to this list and everything worked like magic!

So for example if you have a directive named ‚flight‘, just add |flight to the variable nodeNames in the jQuery file:

var nodeNames = "abbr|article|aside... summary|time|video",  


var nodeNames = "abbr|article|aside... summary|time|video|flight",  

Of course the negative side of this solution is that we need to maintain a slightly changed jQuery file, but we think it is worth.

We don’t use html5shiv or any other special IE handling for custom elements. Only JSON3 and es5-shim are also included to support JSON and some native JS Functions.

Problem 3: ng-repeat and html5 elements

If you are using html5 elements in ng-repeat, the IE will prefix them in the DOM with a colon. See this issue. Otherwise they are perfectly normal elements. The only problem is, that your css selectors for these elements don’t match anymore.

This problem is not easy to fix so we decided to add additional css selectors like :section in the sample below.

section, :section {  
  display: block;

We would appreciate any kind of feedback.