Previously if a template contained a directive that had a template
(sync or async) and the directive template was to replace the original
element and the directive template contained another directive on the
root element of this template and this new directive was an element
transclude directive then an infinite recursion would follow because
the compiler kept on re-adding and reapplying the original directive
to the replaced node.
This change fixes that.
Closes#2155
This reverts commit 0c6fb665a4.
The change invalidated the test because the point of the the test
was to test that an element directive works. Changing it to attribute
directive was wrong.
BREAKING CHANGE: Concatenating expressions makes it hard to reason about
whether some combination of concatenated values are unsafe to use
and could easily lead to XSS. By requiring that a single expression
be used for *[src/ng-src] such as iframe[src], object[src], etc.
(but not img[src/ng-src] since that value is sanitized), we ensure that the value
that's used is assigned or constructed by some JS code somewhere
that is more testable or make it obvious that you bound the value to
some user controlled value. This helps reduce the load when
auditing for XSS issues.
To migrate your code, follow the example below:
Before:
JS:
scope.baseUrl = 'page';
scope.a = 1;
scope.b = 2;
HTML:
<!-- Are a and b properly escaped here? Is baseUrl
controlled by user? -->
<iframe src="{{baseUrl}}?a={{a}&b={{b}}">
After:
JS:
var baseUrl = "page";
scope.getIframeSrc = function() {
// There are obviously better ways to do this. The
// key point is that one will think about this and do
// it the right way.
var qs = ["a", "b"].map(function(value, name) {
return encodeURIComponent(name) + "=" +
encodeURIComponent(value);
}).join("&");
// baseUrl isn't on scope so it isn't bound to a user
// controlled value.
return baseUrl + "?" + qs;
}
HTML: <iframe src="{{getIframeSrc()}}">
jQuery switched to a completely new event binding implementation as of
1.7.0, centering around on/off methods instead of previous bind/unbind.
This patch makes jqLite match this implementation while still supporting
previous bind/unbind methods.
$route, $routeParams and ngView have been pulled from core angular.js
to angular-route.js/ngRoute module.
This is was done to in order keep the core focused on most commonly
used functionality and allow community routers to be freely used
instead of $route service.
There is no need to panic, angular-route will keep on being supported
by the angular team.
Note: I'm intentionally not fixing tutorial links. Tutorial will need
bigger changes and those should be done when we update tutorial to
1.2.
BREAKING CHANGE: applications that use $route will now need to load
angular-route.js file and define dependency on ngRoute module.
Before:
```
...
<script src="angular.js"></script>
...
var myApp = angular.module('myApp', ['someOtherModule']);
...
```
After:
```
...
<script src="angular.js"></script>
<script src="angular-route.js"></script>
...
var myApp = angular.module('myApp', ['ngRoute', 'someOtherModule']);
...
```
Closes#2804
In line with ngSrc and ngHref, this new directive ensures that the
`srcset` HTML5 attribute does not include a pre-interpolated string.
Without it the browser will fetch from the URL with the literal text
`{{hash}}` until AngularJS replaces the expression inside `{{hash}}`.
Closes#2601
Extend ng-options with a new clause, "track by [trackByExpression]", which can be used when
working with objects. The `trackByExpression` should uniquely identify select options objects.
This solves the problem of previously having to match ng-options objects by identity.
You can now write: `ng-options="obj as obj.name for obj in objects track by obj.id"`
The "track by" expression will be used when checking for equality of objects.
Examples:
<select
ng-model="user.favMovieStub"
ng-options="movie as movie.name for movie in movies track by movie.id">
</select>
scope: {
user: { name: 'Test user', favMovieStub: { id: 1, name: 'Starwars' } }
movies: [{ id: 1, name: 'Starwars', rating: 5, ... }, { id: 13, ... }]
}
The select input will match user favMovieStub to the first movie in the movies array, and show
"Star Wars" as the selected item.
BREAKING CHANGE: css classes foo-setup/foo-start become foo/foo-active
The CSS transition classes have changed suffixes. To migrate rename
.foo-setup {...} to .foo {...}
.foo-start {...} to .foo-active {...}
or for type: enter, leave, move, show, hide
.foo-type-setup {...} to .foo-type {...}
.foo-type-start {...} to .foo-type-active {...}
Fix a check inside render for select elements with ngOptions, which
compares the selected property of an element with it's desired state.
Ensure the placeholder, if available, is explicitly selected if the model
value can not be found in the option list.
Without these fixes it's up to the browser implementation to decide which
option to choose. In most browsers, this has the effect of displaying the
first item in the list. In IE9 however, this causes the select to display
nothing.
Closes#2150, #1826
Adding a $includeContentRequested event in order to better keep track of
how many includes are sent and be able to compare it with how many have
finished.
Support ng-controller="MyController as my" syntax
which publishes the controller instance to the
current scope.
Also supports exporting a controller defined with route:
````javascript
angular.module('routes', [], function($routeProvider) {
$routeProvider.when('/home', {controller: 'Ctrl as home', templateUrl: '...'});
});
````
This directive is adapted from ui-if in the AngularUI project and provides a complement
to the ngShow/ngHide directives that only change the visibility of the DOM element and
ngSwitch which does change the DOM but is more verbose.
In IE the model is not updated when the input value is modified using the context
menu, e.g. pasting from the clipboard, or cutting all or part of the current value.
To capture these changes, we bind to the proprietary 'paste' and 'cut' events.
Closes#1462
If you wire up ngClass directly to an object on the scope, e.g. ng-class="myClasses",
where scope.myClasses = { 'classA': true, 'classB': false },
there was a bug that changing scope.myClasses.classA = false, was not being picked
up and classA was not being removed from the element's CSS classes.
This fix uses angular.equals for the comparison and ensures that oldVal is a copy of
(rather than a reference to) the newVal.
Preserve the order of the elements that are not part of a case nor default in
a ng-switch directive
BREAKING CHANGE: elements not in the ng-switch were rendered after the
ng-switch elements. Now they are rendered in-place.
Ng-switch directives should be updated with non ng-switch elements
in render-order. e.g.
The following was previously rendered with <li>1</li> after "2":
<ul ng-switch="select">
<li>1</li>
<li ng-switch-when="option">2</li>
</ul>
To keep the old behaviour, say:
<ul ng-switch="select">
<li ng-switch-when="1">2</li>
<li>1</li>
</ul>
Closes#1074
ngClassWatchAction, when called as a $watch function, gets the wrong old
value after it has been invoked previously due to observation of the
interpolated class attribute. As a result it doesn't remove classes
properly. Keeping track of the old value manually seems to fix this.
Closes#1637
The change to prevent <span> elements being wrapped around empty text nodes caused these empty text nodes to have scopes and controllers attached, through jqLite.data() calls, which led to memory leaks and errors in IE8.
Now we exclude all but document nodes and elements from having jqLite.data() set both in the compiler and in ng-view.
Fixes: #1968 and #1876
Apparently there is a really weird bug in IE6-8 that causes anchor textContent
to be reset with href content when both contain @ symbol.
Inserting a bogus comment node into all anchor elements in IE works around this
browser bug.
I'm fixing the issue via directive because that way we'll fix it for jQuery as
well.
I fixed an e2e test too because it was incorrect.
Closes#1949
The leak can occur when ngSwich is used inside ngRepeat or any other
directive which is destroyed while its transcluded content (which
includes ngSwitch) is not attached to the DOM.
Refactor ngSwitch to use controller instead of storing data on compile
node. This means that we don't need to clean up the jq data cache.
Controller reference is released when the linking fn is released.
Closes#1621
If the $last property is calculated from the original collectionLength
on an object and properties starting with $ were filtered out, then $last
is never applied and $middle is applied erroniously.
Closes#1789
I'm reverting changes that were originally done to ngRepeat to fix#933,
because these are now not necessary after the previous changes to keep
ngModel always synced with the DOM.
Bug caused by the use of the `||` operator to replace all non-truthy
values with an empty string. Changed to replace only `undefined` values.
Closes#1401
Current implementation of ngSrc may lead to empty src attribute when page is loading.
For example:
<img ng-src="{{image.url}}">
can be temporarily rendered as
<img src="">
before the image resource is loaded.
Some browser emits a request to the current page when seeing <img src=""> (Firefox13 and IE8 will, Chromium20 won't), which leads to performance problems.
previously we expected to find option elements only within select element and if
that was not the case we throw an error. This made it impossible to include datalist
element with nested option elements in the template.
Closes#1165
this fix ensures that we prevent the default action on form submission
(full page reload) even in cases when the form is being destroyed as
a result of the submit event handler (e.g. when route change is
triggered).
The fix is more complicated than I'd like it to be mainly because
we need to ensure that we don't create circular references between
js closures and dom elements via DOM event handlers that would then
result in a memory leak.
Also the differences between IE8, IE9 and normal browsers make testing
this ugly.
Closes#1238
the original test relied on incorrect assumptions about how jasmine async
tests work (when setTimeout is triggered) and how browser reloads a page
(the sequence of events) and thus the test passes even when the default
is not prevented.
this change fixes the test by registering an extra submit event handler
that checks if the default was prevented.
if the default was not prevented, the test will fail and the page will
be reloaded causing the test runner to panic.
Changed the isolate scope binding options to:
- @attr - attribute binding (including interpolation)
- =model - by-directional model binding
- &expr - expression execution binding
This change simplifies the terminology as well as
number of choices available to the developer. It
also supports local name aliasing from the parent.
BREAKING CHANGE: isolate scope bindings definition has changed and
the inject option for the directive controller injection was removed.
To migrate the code follow the example below:
Before:
scope: {
myAttr: 'attribute',
myBind: 'bind',
myExpression: 'expression',
myEval: 'evaluate',
myAccessor: 'accessor'
}
After:
scope: {
myAttr: '@',
myBind: '@',
myExpression: '&',
// myEval - usually not useful, but in cases where the expression is assignable, you can use '='
myAccessor: '=' // in directive's template change myAccessor() to myAccessor
}
The removed `inject` wasn't generaly useful for directives so there should be no code using it.
$position marker doesn't work well in cases when we have just one item
in the list because then the item is both the first and last. To solve
this properly we need to expose individual $first and $middle and $last
flags.
BREAKING CHANGE: $position is not exposed in repeater scopes any more
To update, search for $position and replace it with one of $first,
$middle or $last.
Closes#912
IE9 ignores setAttribute('src', val) calls on img if "ng:src" attribute
is present. It only fetches the image if element property is updated as well.
Closes#935
On IE9 the input event is not fired when backspace or delete key are pressed or when
cut is performed. This makes listening on the input event unreliable and therefore
it's better for us to just use keydown/change events instead.
Closes#879
CSP (content security policy) forbids apps to use eval or
Function(string) generated functions (among other things). For us to be
compatible, we just need to implement the "getterFn" in $parse without
violating any of these restrictions.
We currently use Function(string) generated functions as a speed
optimization. With this change, it will be possible to opt into the CSP
compatible mode using the ngCsp directive. When this mode is on Angular
will evaluate all expressions up to 30% slower than in non-CSP mode, but
no security violations will be raised.
In order to use this feature put ngCsp directive on the root element of
the application. For example:
<!doctype html>
<html ng-app ng-csp>
...
...
</html>
Closes#893
Previously only when ngOptions was used, we correctly handled situations
when model was set to an unknown value. With this change, we'll add/remove
extra unknown option or reuse an existing empty option (option with value
set to "") when model is undefined.
Create build for other modules as well (ngResource, ngCookies):
- wrap into a function
- add license
- add version
Breaks `$sanitize` service, `ngBindHtml` directive and `linky` filter were moved to the `ngSanitize` module. Apps that depend on any of these will need to load `angular-sanitize.js` and include `ngSanitize` in their dependency list: `var myApp = angular.module('myApp', ['ngSanitize']);`
The purpose of allowing the scope to be specified was to enable the $route service to work
together with ngInclude. However the functionality of creating scopes was in the recent past
moved from the $route service to the ngView directive, so currently there is no valid use case
for specifying the scope for ngInclude. In fact, allowing the scope to be defined can under
certain circumstances lead to memory leaks.
Breaks ngInclude does not have scope attribute anymore.
It turns out that listening only on "blur" event is not sufficient in many scenarios,
especially when you use form validation you always had to use ngModelnstant
e.g. if you want to disable a button based on valid/invalid form.
The feedback we got from our apps as well as external apps is that the
ngModelInstant should be the default.
In the future we might provide alternative ways of suppressing updates
on each key stroke, but it's not going to be the default behavior.
Apps already using the ngModelInstant can safely remove it from their
templates. Input fields without ngModelInstant directive will start propagating
the input changes into the model on each key stroke.