Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(ngRoute): allow ngView to be included in an asynchronously loaded template #14893

Closed

Conversation

gkalpak
Copy link
Member

@gkalpak gkalpak commented Jul 11, 2016

What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
80% Feature / 20% Bug fix (depending on your angle 😄)

What is the current behavior? (You can also link to an open issue here)
When ngView is loaded asynchronously (e.g. appears in another directive's template), the initial navigation is "missed" (i.e. the corresponding view is never loaded).
See #1213.

What is the new behavior (if this is a feature change)?
Regardless of when ngView is loaded, the initial view is loaded correctly.

Does this PR introduce a breaking change?
Yes.

Please check if the PR fulfills these requirements

Other information:
During its linking phase, ngView relies on the info provided in $route.current for
instantiating the initial view. $route.current is set in the callback of a listener to
$locationChangeSuccess, which is registered during the instantiation of the $route service.

Thus, it is crucial that the $route service is instantiated before the initial
$locationChangeSuccess event is fired. Since ngView declares $route as a dependency, the
service is instantiated in time, if ngView is present during the initial load of the page.

Yet, in cases where ngView is included in a template that is loaded asynchronously (e.g. in
another directive's template), the directive factory might not be called soon enough for $route
to be instantiated before the initial $locationChangeSuccess event is fired.

This commit fixes it, by enabling eager instantiation of $route (during the initialization phase).
Eager instantiation can be disabled (restoring the old behavior), but is on by default.

Fixes #1213

BREAKING CHANGE:

In cases where ngView was loaded asynchronously, $route (and its dependencies; e.g. $location)
might also have been instantiated asynchronously. After this change, $route (and its dependencies)
will - by default - be instantiated early on.

Although this is not expected to have unwanted side-effects in normal application bebavior, it may
affect your unit tests: When testing a module that (directly or indirectly) depends on ngRoute, a
request will be made for the default route's template. If not properly "trained", $httpBackend
will complain about this unexpected request.

You can restore the previous behavior (and avoid unexpected requests in tests), by using
$routeProvider.eagerInstantiationEnabled(false).

…ded template

During its linking phase, `ngView` relies on the info provided in `$route.current` for
instantiating the initial view. `$route.current` is set in the callback of a listener to
`$locationChangeSuccess`, which is registered during the instantiation of the `$route` service.

Thus, it is crucial that the `$route` service is instantiated _before_ the initial
`$locationChangeSuccess` event is fired. Since `ngView` declares `$route` as a dependency, the
service is instantiated in time, if `ngView` is present during the initial load of the page.

Yet, in cases where `ngView` is included in a template that is loaded asynchronously (e.g. in
another directive's template), the directive factory might not be called soon enough for `$route`
to be instantiated before the initial `$locationChangeSuccess` event is fired.

This commit fixes it, by enabling eager instantiation of `$route` (during the initialization phase).
Eager instantiation can be disabled (restoring the old behavior), but is on by default.

Fixes angular#1213

BREAKING CHANGE:

In cases where `ngView` was loaded asynchronously, `$route` (and its dependencies; e.g. `$location`)
might also have been instantiated asynchronously. After this change, `$route` (and its dependencies)
will - by default - be instantiated early on.

Although this is not expected to have unwanted side-effects in normal application bebavior, it may
affect your unit tests: When testing a module that (directly or indirectly) depends on `ngRoute`, a
request will be made for the default route's template. If not properly "trained", `$httpBackend`
will complain about this unexpected request.

You can restore the previous behavior (and avoid unexpected requests in tests), by using
`$routeProvider.eagerInstantiationEnabled(false)`.
@gkalpak
Copy link
Member Author

gkalpak commented Jul 11, 2016

BTW, it was originally fixed (in a breaking fashion) in 5e37b2a, which was then reverted with 75bf807.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Initial route update doesn't happen if ngView in a template loaded by ngInclude
2 participants