AngularJS scope variable not getting evaluated inside IE's conditional comment - angularjs

I have to use two iframes, one for IE8 and other for the rest of the browsers. I see that the angularjs scope variable (myUrl) is getting evaluated for the later iframe but not the first.
<div id="frameContainer" class="modal-body ios-scroll">
<!--[if IE 8]><iframe ng-src="{{myUrl}}?domain=http://localhost:9001/" class="signInIframe" frameborder="0" marginheight="0" marginwidth="0" height="620" width="600"></iframe> <![endif]-->
<!--[if (gt IE 8)|!(IE)]><!--> <iframe ng-src="{{myUrl}}?domain=http://localhost:9001/" class="signInIframe" frameborder="0" marginheight="0" marginwidth="0" height="100%" width="100%"></iframe><!--<![endif]-->
</div>

Your problem may lie with Internet Explorer 8 and lower having problems with custom attributes. (e.g. ng-src)
Check out this guide for more information.
This document describes the Internet Explorer (IE) idiosyncrasies when dealing with custom HTML attributes and tags. Read this document if you are planning on deploying your Angular application on IE v8.0 or earlier. (emphasis mine)
To see if this is indeed the case, try doing what kmdsax suggested by changing ng-src to simply src. If that works, then your issue is most likely the custom attribute.
NOTE: According to the docs, if you don't use ng-src then your iframe won't resolve to the correct address. So make sure you read that IE compatibility guide to make IE8 and lower behave.

I tested your code in IE8 and it seems to be working fine.
You dont really need to use ng-src here, you can also use src, and the {{myUrl}} variable will be evaluated the same. Try that, see if it makes a difference for you.

Related

When to use ngAttr?

Just wanted some clarifications. I was told that you are suppose to use ngAttr when there are interpolated markup. For example:
<div ng-attr-name={{Name}}></div>
I also seen some codes online where there are interpolated markups but they do not use ngAttr. Are there certain situations when you use ngAttr and not use ngAttr when dealing with interpolated markups?
I recall running into this issue when working with <svg/> and attempting to interpolate attributes such as cx (which happens to be the classic example in the current angularjs documentation). The browser will complain when you attempt the following:
<svg>
<circle cx="{{cx}}"></circle>
</svg>
due to restrictions when using the SVG DOM API. Therefore, the ng-attr directive comes in handy with
<svg>
<circle ng-attr-cx="{{cx}}"></circle>
</svg>
As a result, using the `ng-attr- directive in this scenario will appropriately set the value based on your binding. Now, what I have noticed new in the documentation are the following cases that have known to cause issues if you don't use ng-attr
size in elements (see issue 1619)
placeholder in in Internet Explorer 10/11 (see issue 5025)
type in in Internet Explorer 11 (see issue 14117)
value in in Internet Explorer = 11 (see issue 7218)

Use of ng-src vs src

This tutorial demonstrates the use of the directive ngSrc instead of src :
<ul class="phones">
<li ng-repeat="phone in phones" class="thumbnail">
<img ng-src="{{phone.imageUrl}}">
</li>
</ul>
They ask to:
Replace the ng-src directive with a plain old src attribute.
Using tools such as Firebug, or Chrome's Web Inspector, or inspecting the
webserver access logs, confirm that the app is indeed making an
extraneous request to /app/%7B%7Bphone.imageUrl%7D%7D (or
/app/{{phone.imageUrl}}).
I did so and it gave me the correct result:
<li class="thumbnail ng-scope" ng-repeat="phone in phones">
<img src="img/phones/motorola-xoom.0.jpg">
</li>
Is there a reason why?
From Angular docs
The buggy way to write it:
<img src="http://www.gravatar.com/avatar/{{hash}}"/>
The correct way to write it:
<img ng-src="http://www.gravatar.com/avatar/{{hash}}"/>
Why? this is because on load of page, before angular bootstrapping and creation of controllers, browser will try to load image from http://www.gravatar.com/avatar/{{hash}} and it will fail. Then once angular is started, it understands that that {{hash}} has to be replaced with say logo.png, now src attribute changes to http://www.gravatar.com/avatar/logo.png and image correctly loads. Problem is that there are 2 requests going and first one failing.
TO solve this we should use ng-src which is an angular directive and angular will replace ng-src value into src attribute only after angular bootstrapping and controllers are fully loaded, and at that time {{hash}} would have already been replaced with correct scope value.
<img ng-src="{{phone.imageUrl}}">
This gives you expected result, because phone.imageUrl is evaluated and replaced by its value after angular is loaded.
<img src="{{phone.imageUrl}}">
But with this, the browser tries to load an image named {{phone.imageUrl}}, which results in a failed request.
You can check this in the console of your browser.
The src="{{phone.imageUrl}}" is unnecessary and creates an extra request by the browser. The browser will make at least 2 GET requests attempting to load that image:
before the expression is evaluated {{phone.imageUrl}}
after the expression is evaluated img/phones/motorola-xoom.0.jpg
You should always use ng-src directive when dealing with Angular expressions. <img ng-src="{{phone.imageUrl}}"> gives you the expected result of a single request.
On a side note, the same applies to ng-href so you don't get broken links till the first digest cycle kicks in.
Well actually it makes 100% sense because HTML gets processed sequentially and when this HTML page is being processed line by line, by the time it gets to this image, the line and processing the image, our phone.imageUrl is not yet defined yet.
And in fact, Angular JS has not yet processed this chunk of HTML, and hasn't yet looked for these placeholders and substitute these expressions with the values. So what ends up happening is that the browser gets this line and tries to fetch this image at this URL.
And of course this is a bogus URL, if it still has those mustache and curly braces in it, and therefore it gives you a 404, but once of course Angular takes care of this, it substitutes this URL for the proper one, and then we still see the image, but yet the 404 error message remains in our console.
So, how can we take care of this? Well, we can not take care of this using regular HTML tricks. But, we can take care of it using Angular. We need somehow to tell the browser not to try to fetch this URL but at the same time fetch it only when Angular is ready for interpretation of these placeholders.
Well, one way of doing it is to put an Angular attribute on here instead of the standard HTML one. And the Angular attribute is just ng-src. So if we say that now, go back, you'll see that there's no errors anymore because the image only got fetched once Angular got a hold of this HTML and translated all the expressions into their values.

Why is it that I see {{ ... }} before loading in AngularJS?

Do you know why is the {{ project.title }} before I see the real value of the scope.
And how to solve that ?
EDIT : <title>{{ pageTitle }}</title>
Page is loading
Page completely loaded
Your views for Angular.JS apps are just static HTML. If you remove the script tag that references Angular.JS, you'd end up with a page full of curly brackets in plain sight that never get replaced.
When your browser finished loading Angular.JS and loading your application, the expressions in those curly brackets are evaluated. That's why you see, for a brief moment, {{…}} in your page title.
As noted by others, the ng-cloak directive is usually the way to get rid of the flickering before the app is fully loaded.
But since ng-cloak is just CSS, it cannot be applied to the page title. You'll need ng-bind for that, as noted here.
<title ng-bind="pageTitle">Default Title</title>
You should be showing the code, but in general it's probably because you aren't using ng-cloak https://docs.angularjs.org/api/ng/directive/ngCloak
However, in the case of the title, you need to use ng-bind=project.title instead <title>{{ project.title }}</title>
Check How to hide {{title}} in <title> tag while using AngularJS?
To prevent this, you should use ng-bind instead of {{ }} for the first screen of your app.
ng-bind is a directive that is added to an element attribute, so it is displayed only when the page is loaded.
According to the description of ngBind, we usually use {{ expression }} to replace ng-bind. But in a first-loading situation, image that you firstly load AngularJS(maybe in index.html), it'll show the original {{ }}. After that, it transits to what u need. To overcome it, you can use ngCloak or just use ng-bind in your first page.
OK, please check this ?

Hide Angular brackets until javascript loaded

I have a few bits of HTML like
<p class="noresults">{{numberOfContacts}} Results Are Available</p>
Is it possible for me to hide {{numberOfContacts}} until Angular has loaded? So it would just say Results Are Available
I've seem some solutions such as hiding the entire body until Angular has loaded, but I'd rather not do that if possible.
Yes, use ng-cloak. Simply add class="ng-cloak" or ng-cloak to an element like this
Using directive <div ng-cloak></div>
Using class <div class="ng-cloak"></div>
It's simply a set of CSS rules with display: none !important and as Angular has rendered your DOM it removes the ng-cloak so an element is visible.
use <span ng-bind="numberOfContacts" /> instead of {{numberOfContacts}}
Sometimes, even if I used the ng-cloak, I could still see the braces for a few seconds. Adding the following style resolved my issue:
[ng-cloak]
{
display: none !important;
}
Please see this link link for more explanation.
Hope it helps :D
This is typically only an issue when working with complex content on really slow devices. In those instances, there can be a brief moment when the browser displays the HTML in the document while AngularJS is parsing the HTML, getting ready, and processing the directives. In this interval of time, any inline template expressions you have defined will be visible to the user. Most devices nowadays have pretty good browsers which are quick enough to prevent this from being an issue. There are two ways to solve the problem.
Avoid using inline template expressions and stick with ng-bind directive.
(Best) Use the ng-cloak directive which will hide the content until Angular has finished processing it. Basically, the ng-cloak directive uses CSS to hide the elements and angular removes the CSS class when the content has been processed, ensuring that the user never sees the {{ and }} characters of a template expression.
One strategy to consider is using the ng-cloak directly to the body element, which will ensure that the user will see an empty browser while AngularJS loads. However, you can be more specific by applying it to parts of the document where there are inline expressions.
I have seen issues with ng-cloak not working when added to an element. In the past, I have worked around this issue by simply adding ng-cloak class to element.
You can use ng-bind instead of expression like
<span ng-bind="data"></span>

Directive not working in IE8

I have a directive called barsMax and it is not working in IE8, even if I already placed:
<!--[if lte IE 8]>
<script>
document.createElement('bars-max');
</script>
<![endif]-->
What am I missing?
Code you are using also has a pseudo tag bars-current.
Adding document.createElement('bars-current'); to your polyfill worked for me.
DISCLAMER : Am Using IE10 in IE8 standards mode but error thrown in console if don't create elements first and jsfiddle itself falls apart without it in IE8
DEMO Working version
IE doesnt allow unfamiliar tags and therefor you may not use directives as tags like . you must use restrict "A" and use it as an attribute in a known html tag. if you dont want the wrapper tag use replace:true like this
return {
restrict: 'A',
replace:true,
scope: ...,
link:...
you can see some examples about all that here https://skydrive.live.com/redir?resid=949DC4EDBFFD4738!189&authkey=!ABZCTBTTOCDYGhk
working version tested in ie8 native http://jsbin.com/IDOMuqU/2/edit
(the not working version in ie8 native with the polyfills - http://jsbin.com/IDOMuqU/1/edit)

Resources