The `routeToRegExp()` function, introduced by 840b5f0, could not extract
path params if the path contained question mark or hash. Although these
characters would normally be encoded in the path, they are decoded by
`$location.path()`, before being passed to the RegExp returned by
`routeToRegExp()`.
`routeToRegExp()` has to be able to deal with both encoded URL and
decoded path, because it is being shared between `ngRoute` and
`ngMocks`.
This commit fixes the issue, by introducing an `isUrl` option that
allows creating an appropriate RegExp for each usecase.
Interpolated content in ngHref must be stringified before being passed to $$sanitizeUri by $sce. Before 1.7.x, the sanitization had happened on the already interpolated value inside $compile.
Closes#16652Fixes#16626
Previously, the value observer incorrectly assumed a value had changed even if
it was the first time it was set, which caused it to remove an option with
the value `undefined` from the internal option map.
Fixes#16653Closes#16656
The issue in question has been resolved some time in 2017.
The bug report is still open, but the behavior has changed:
https://bugzilla.mozilla.org/show_bug.cgi?id=126379
Let's hope they have tests for this!
Properties:
Previously only arbitrary DOM attribute bindings were supported via interpolation such as
`my-attribute="{{expression}}"` or `ng-attr-my-attribute="{{expression}}"`, and only a set of
distinct properties could be bound. `ng-prop-*` adds support for binding expressions to any DOM
properties. For example `ng-prop-foo="x"` will assign the value of the expression `x` to the
`foo` property, and re-assign whenever the expression `x` changes.
Events:
Previously only a distinct set of DOM events could be bound using directives such as `ng-click`,
`ng-blur` etc. `ng-on-*` adds support for binding expressions to any DOM event. For example
`ng-on-bar="barOccured($event)"` will add a listener to the "bar" event and invoke the
`barOccured($event)` expression.
Since HTML attributes are case-insensitive, property and event names are specified in snake_case
for `ng-prop-*` and `ng-on-*`. For example, to bind property `fooBar` use `ng-prop-foo_bar`, to
listen to event `fooBar` use `ng-on-foo_bar`.
Fixes#16428Fixes#16235Closes#16614
When disabling/enabling animations on a specific element (via
`$animate.enabled(element, enabled)`), the element is added in a map to
track its state. Previously, the element was never removed from the map,
causing AngularJS to hold on to the element even after it is removed
from the DOM, thus preventing it from being garbage collected.
This commit fixes it by removing the element from the map on `$destroy`.
Fixes#16637.
Closes#16649
Digest cycle already in progress error can inadvertently be caused when triggering an
element's click event while within an active digest cycle. This is due to the ngEventsDirs
event handler always calling $rootScope.$apply regardless of the status of $rootScope.$$phase.
Checking the phase and calling the function immediately if within an active digest cycle
will prevent the problem without reducing current functionality.
Closes#14673Closes#14674
This shouldn't happen in supported jQuery versions (2+), but if someone
uses the unsupported 1.x version the app will break. The change that
causes this new behavior was introduced in b7d396b8b.
Even though jQuery 1.x is not supported, it is worth avoiding the
unnecessary breakage (given how simple).
Fixes#16641Closes#16642
For historical reasons, `$timeout.verifyNoPendingTasks()` throws if
there is any type of task pending (even if it is not a timeout). When
calling `$timeout.verifyNoPendingTasks()`, the user is most likely
interested in verifying pending timeouts only, which is now possible
with `$verifyNoPendingTasks('$timeout')`.
To raise awareness of `$verifyNoPendingTasks()`, it is mentioned in the
error message thrown by `$timeoutverifyNoPendingTasks()` if none of the
pending tasks is a timeout.
`$flushPendingTasks([delay])` allows flushing all pending tasks (or up
to a specific delay). This includes `$timeout`s, `$q` promises and tasks
scheduled via `$rootScope.$applyAsync()` and `$rootScope.$evalAsync()`.
(ATM, it only flushes tasks scheduled via `$browser.defer()`, which does
not include `$http` requests and `$route` transitions.)
`$verifyNoPendingTasks([taskType])` allows verifying that there are no
pending tasks (in general or of a specific type). This includes tasks
flushed by `$flushPendingTasks()` as well as pending `$http` requests
and in-progress `$route` transitions.
Background:
`ngMock/$timeout` has `flush()` and `verifyNoPendingTasks()` methods,
but they take all kinds of tasks into account which is confusing. For
example, `$timeout.verifyNoPendingTasks()` can fail (even if there are
no pending timeouts) because of an unrelated pending `$http` request.
This behavior is retained for backwards compatibility, but the new
methods are more generic (and thus less confusing) and also allow
more fine-grained control (when appropriate).
Closes#14336
Previously, all pending async tasks (tracked via `$browser`) are treated
the same. I.e. things like `$$testability.whenStable()` and
`ngMock#$timeout.verifyNoPendingTasks()` take all tasks into account.
Yet, in some cases we might be interested in specific tasks only. For
example, if one wants to verify there are no pending `$timeout`s, they
don't care if there are other pending tasks, such as `$http` requests.
Similarly, one might want to get notified when all `$http` requests have
completed and does not care about pending promises.
This commit adds support for more granular task tracking, by enabling
callers to specify the type of task that is being added/removed from the
queue and enabling listeners to be triggered when specific types of
tasks are completed (even if there are more pending tasks of different
types).
The change is backwards compatible. I.e. calling the affected methods
with no explicit task-type, behaves the same as before.
Related to #14336.
Some characters are treated differently by `$location` compared to `$browser` and
the native browser. When comparing URLs across these two services this must be
taken into account.
Fixes#16592Closes#16611
DOM nodes passed to `compilationGenerator()` will eventually be wrapped
in `jqLite`, when the compilation actually happens. In Firefox 60+,
there seems to be a `DocumentFragment`-related bug that sometimes causes
the `childNodes` to be empty at the time the compilation happens.
This commit works around this bug by eagerly wrapping `childNodes` in
`jqLite`.
NOTE:
The wrapped nodes have references to their `DocumentFragment` container.
This is "by design", since we want to be able to traverse the nodes via
`nextSibling` (in order to correctly handle multi-element directives).
Once the nodes are compiled, they will be either moved to a new
container element or the `jqLite` wrapper is release making them
eligible for garbage collection. In both cases, the original
`DocumentFragment` container should be eligible for garbage collection
too.
Fixes#16607Closes#16615
Background:
ngAnimate writes helper classes to DOM elements to see if animations are defined on them. If many
elements have the same definition, and the same parent, we can cache the definition and skip the
application of the helper classes altogether. This helps particularly with large ngRepeat
collections.
Closes#14165Closes#14166Closes#16613