I've been working through the Angular.JS tutorial, and I'm on step 6. The tutorial shows the following code snippet:
<ul class="phones">
<li ng-repeat="phone in phones | filter:query | orderBy:orderProp" class="thumbnail">
<a href="#/phones/{{phone.id}}" class="thumb"><img ng-src="{{phone.imageUrl}}"></a>
<a href="#/phones/{{phone.id}}">{{phone.name}}</a>
<p>{{phone.snippet}}</p>
</li>
</ul>
It then goes on to explain:
We also added ... the ngSrc directive. That directive prevents the browser from treating the angular {{ expression }} markup literally, and initiating a request to invalid url /app/{{phone.imageUrl}}, which it would have done if we had only specified an attribute binding in a regular src attribute (). Using the ngSrc directive prevents the browser from making an http request to an invalid location.
So, what it's saying is, the img element needs to use the special Angular.JS directive ngSrc so it can correctly parse the double curly braces. But they fail to explain why the a element doesn't require the same special directive.
<a href="#/phones/{{phone.id}}">
What's going on here? href can correctly parse the double curly braces, but src can't? Why?
To add to David's great answer, the basic difference is that the href doesn't trigger any server calls on page load (because there is no reason to, it's triggered only when you follow the link), while, on the other hand, all image tags are loaded when the page loads, and of course, the server tries to fetch them right away as their path is found in the src attribute.
The problem is that the DOM is loaded much before angular is (because DOM initiates angular), so there is no parsing/interpolation taking place before the angular loads, but all the image tags are ready and system is starting to fetch them. At that point, the source for your image is
{{phone.imageUrl}}
and it will try to fetch that first, returning errors.ng-src avoids this default behaviour, and adds the src to the image once the angular is ready.
The AngularJS docs are great place to find this type of information.
http://docs.angularjs.org/api/ng/directive/ngSrc
There is actually a
ng-href
directive:http://docs.angularjs.org/api/ng/directive/ngHref
So essentially what this all means is that if you write a url like this:
However, the hashes inside the URL can be an issue if Angular hasn't loaded yet. If the user attempts to click that link before Angular binds the link will literally be the
{{ phone.id }}
rather than the actual bound value.How often, does this happen? Well it depends on how long it takes your page to load. If you're resolving a promise onto the page without resolving the route then the user will definitely have a chance to click the improper link.
Long story short, different directives, same reasoning.