Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(common): add a LocationUpgradeService to mimic AngularJS functionality #30055

Closed
wants to merge 13 commits into from

Conversation

jasonaden
Copy link
Contributor

This PR contains a handful of features related to location services.

Read history.state

Previously there wasn't a way to retrieve history.state from the Location service. The only time the framework exposed this value was in navigation events. This meant if you weren't using the Angular router, there wasn't a way to get access to this history.state value other than going directly to the DOM.

This PR adds an API to retrieve the value of history.state. This will be useful and needed to provide a backwards-compatible Location service that can emulate AngularJS's $location service since we will need to be able to read the state data in order to produce AngularJS location transition events.

This feature will additionally be useful to any application that wants to access state data through Angular rather than going directly to the DOM APIs.

Read URL parts

Without this change, the framework doesn't surface URL parts such as hostname, protocol, and port. This makes it difficult to rebuild a complete URL. This change provides new APIs to read these values.

Location Upgrade ($location)

This PR provides a replacement for $location. The new service is written in Angular, and can be consumed into existing applications by using the downgraded version
of the provider.

Prior to this addition, applications upgrading from AngularJS to Angular could get into a situation where AngularJS wanted to control the URL, and would often parse or serialize the URL in a different way than Angular. Additionally, AngularJS was alerted to URL changes only through the $digest cycle. This provided a buggy feedback loop
from Angular to AngularJS.

With this new LocationUpgradeProvider, the $location methods and events are provided in Angular, and use Angular APIs to make updates to the URL. Additionally, change
s to the URL made by other parts of the Angular framework (such as the Router) will be listened for and will cause events to fire in AngularJS, but will no longer attempt
to update the URL (since it was already updated by the Angular framework).

This centralizes URL reads and writes to Angular and should help provide an easier path to upgrading AngularJS applications to Angular.

…of Location services

Prior to this change we had a MockLocationStrategy to replace the Path and Hash Location Strategies. However, there wasn't a good way to test the PlatformLocation which is needed for doing things such as setting history.state, using back()/forward(), etc.
Previously there wasn't a way to retrieve `history.state` from the `Location` service. The only time the framework exposed this value was in navigation events. This meant if you weren't using the Angular router, there wasn't a way to get access to this `history.state` value other than going directly to the DOM.

This PR adds an API to retrieve the value of `history.state`. This will be useful and needed to provide a backwards-compatible `Location` service that can emulate AngularJS's `$location` service since we will need to be able to read the state data in order to produce AngularJS location transition events.

This feature will additionally be useful to any application that wants to access state data through Angular rather than going directly to the DOM APIs.
Without this change, the framework doesn't surface URL parts such as hostname, protocol, and port. This makes it difficult to rebuild a complete URL. This change provides new APIs to read these values.
…ed APIs

AngularJS's `$location` service doesn't have a direct counterpart in Angular. This is largely because the `Location` service in Angular was pulled out of the `Router`, but was not purpose-built to stand on its own.

This commit adds a new `@angular/common/upgrade` package with the beginnings of a new `LocationUpgradeService`. This service will more closely match the API of AngularJS and provide a way to replace the `$location` service from AngularJS.
This feature adds an `onUrlChange` to Angular's `Location` class. This is useful to track all updates coming from anywhere in the framework. Without this method, it's difficult (or impossible) to track updates run through `location.go()` or `location.replaceState()` as the browser doesn't publish events when `history.pushState()` or `.replaceState()` are run.
When using the `history` API, setting a new `state` and retrieving it does not pass a `===` test to the object used to set the state. In other words, `history.state` is always a copy. This change makes the `MockPlatformLocation` behave in the same way.
This abstract class (and AngularJSUrlCodec) are used for serializing and deserializing pieces of a URL string. AngularJS had a different way of doing this than Angular, and using this class in conjunction with the LocationUpgradeService an application can have control over how AngularJS URLs are serialized and deserialized.
This commit provides a replacement for `$location`. The new service is written in Angular, and can be consumed into existing applications by using the downgraded version
of the provider.

Prior to this addition, applications upgrading from AngularJS to Angular could get into a situation where AngularJS wanted to control the URL, and would often parse or se
rialize the URL in a different way than Angular. Additionally, AngularJS was alerted to URL changes only through the `$digest` cycle. This provided a buggy feedback loop
from Angular to AngularJS.

With this new `LocationUpgradeProvider`, the `$location` methods and events are provided in Angular, and use Angular APIs to make updates to the URL. Additionally, change
s to the URL made by other parts of the Angular framework (such as the Router) will be listened for and will cause events to fire in AngularJS, but will no longer attempt
 to update the URL (since it was already updated by the Angular framework).

This centralizes URL reads and writes to Angular and should help provide an easier path to upgrading AngularJS applications to Angular.
@benlesh benlesh added the area: common Issues related to APIs in the @angular/common package label Apr 23, 2019
@ngbot ngbot bot added this to the needsTriage milestone Apr 23, 2019
packages/common/test/location/location_spec.ts Outdated Show resolved Hide resolved
packages/common/upgrade/rollup.config.js Outdated Show resolved Hide resolved
packages/common/testing/src/mock_platform_location.ts Outdated Show resolved Hide resolved
packages/common/src/location/location.ts Outdated Show resolved Hide resolved
packages/common/testing/tsconfig-build.json Show resolved Hide resolved
packages/common/upgrade/src/params.ts Show resolved Hide resolved
packages/common/upgrade/BUILD.bazel Show resolved Hide resolved
private initalizing = true;
private updateBrowser = false;
private $$absUrl: string = '';
private $$url: string = '';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that we intentionally provide these $$ fields because people read from them (and so technically they're here to be interface compatible with AngularJS), I would go ahead and make them public API. We want our public API guard to ensure they're not changed without consideration.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have this discussion with Igor to see what he thinks. I'm inclined to leave it out because if people are already using TypeScript from Definitely Typed, they will not have these and would have to do casting anyway. See type definition here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I was more thinking that we want to make sure we don't inadvertently change any of this API, but maybe having the documentation in place that the class mirrors AngularJS's interface is enough.

packages/common/upgrade/src/$location.ts Outdated Show resolved Hide resolved
@jasonaden jasonaden marked this pull request as ready for review April 23, 2019 23:46
@jasonaden jasonaden requested review from a team as code owners April 23, 2019 23:46
@jasonaden
Copy link
Contributor Author

jasonaden commented Apr 24, 2019

Copy link
Contributor

@IgorMinar IgorMinar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's rename some of the symbols and remove the $locationProvider and peerDep on @angular/upgrade. the rest lgtm from the api perspective.

tools/public_api_guard/common/upgrade.d.ts Outdated Show resolved Hide resolved
tools/public_api_guard/common/upgrade.d.ts Outdated Show resolved Hide resolved
tools/public_api_guard/common/upgrade.d.ts Outdated Show resolved Hide resolved
html5Mode(mode?: any): void;
}

export declare class LocationUpgradeService {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename

benlesh pushed a commit that referenced this pull request Apr 24, 2019
This feature adds an `onUrlChange` to Angular's `Location` class. This is useful to track all updates coming from anywhere in the framework. Without this method, it's difficult (or impossible) to track updates run through `location.go()` or `location.replaceState()` as the browser doesn't publish events when `history.pushState()` or `.replaceState()` are run.

PR Close #30055
benlesh pushed a commit that referenced this pull request Apr 24, 2019
…30055)

When using the `history` API, setting a new `state` and retrieving it does not pass a `===` test to the object used to set the state. In other words, `history.state` is always a copy. This change makes the `MockPlatformLocation` behave in the same way.

PR Close #30055
benlesh pushed a commit that referenced this pull request Apr 24, 2019
…0055)

This abstract class (and AngularJSUrlCodec) are used for serializing and deserializing pieces of a URL string. AngularJS had a different way of doing this than Angular, and using this class in conjunction with the LocationUpgradeService an application can have control over how AngularJS URLs are serialized and deserialized.

PR Close #30055
benlesh pushed a commit that referenced this pull request Apr 24, 2019
…0055)

This commit provides a replacement for `$location`. The new service is written in Angular, and can be consumed into existing applications by using the downgraded version
of the provider.

Prior to this addition, applications upgrading from AngularJS to Angular could get into a situation where AngularJS wanted to control the URL, and would often parse or se
rialize the URL in a different way than Angular. Additionally, AngularJS was alerted to URL changes only through the `$digest` cycle. This provided a buggy feedback loop
from Angular to AngularJS.

With this new `LocationUpgradeProvider`, the `$location` methods and events are provided in Angular, and use Angular APIs to make updates to the URL. Additionally, change
s to the URL made by other parts of the Angular framework (such as the Router) will be listened for and will cause events to fire in AngularJS, but will no longer attempt
 to update the URL (since it was already updated by the Angular framework).

This centralizes URL reads and writes to Angular and should help provide an easier path to upgrading AngularJS applications to Angular.

PR Close #30055
benlesh pushed a commit that referenced this pull request Apr 24, 2019
benlesh pushed a commit that referenced this pull request Apr 24, 2019
brandonroberts added a commit to brandonroberts/angular that referenced this pull request Apr 25, 2019
…common

Follow-up to angular#30055 to include @angular/common/upgrade in the npm package

Closes angular#30116
brandonroberts added a commit to brandonroberts/angular that referenced this pull request Apr 25, 2019
…common

Follow-up to angular#30055 to include @angular/common/upgrade in the npm package

Closes angular#30116
brandonroberts added a commit to brandonroberts/angular that referenced this pull request Apr 25, 2019
…common

Follow-up to angular#30055 to include @angular/common/upgrade in the npm package

Closes angular#30116
brandonroberts added a commit to brandonroberts/angular that referenced this pull request Apr 25, 2019
…common

Follow-up to angular#30055 to include @angular/common/upgrade in the npm package

Closes angular#30116
AndrewKushnir pushed a commit that referenced this pull request Apr 25, 2019
…common (#30117)

Follow-up to #30055 to include @angular/common/upgrade in the npm package

Closes #30116

PR Close #30117
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…of Location services (angular#30055)

Prior to this change we had a MockLocationStrategy to replace the Path and Hash Location Strategies. However, there wasn't a good way to test the PlatformLocation which is needed for doing things such as setting history.state, using back()/forward(), etc.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…angular#30055)

Previously there wasn't a way to retrieve `history.state` from the `Location` service. The only time the framework exposed this value was in navigation events. This meant if you weren't using the Angular router, there wasn't a way to get access to this `history.state` value other than going directly to the DOM.

This PR adds an API to retrieve the value of `history.state`. This will be useful and needed to provide a backwards-compatible `Location` service that can emulate AngularJS's `$location` service since we will need to be able to read the state data in order to produce AngularJS location transition events.

This feature will additionally be useful to any application that wants to access state data through Angular rather than going directly to the DOM APIs.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
Without this change, the framework doesn't surface URL parts such as hostname, protocol, and port. This makes it difficult to rebuild a complete URL. This change provides new APIs to read these values.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…ed APIs (angular#30055)

AngularJS's `$location` service doesn't have a direct counterpart in Angular. This is largely because the `Location` service in Angular was pulled out of the `Router`, but was not purpose-built to stand on its own.

This commit adds a new `@angular/common/upgrade` package with the beginnings of a new `LocationUpgradeService`. This service will more closely match the API of AngularJS and provide a way to replace the `$location` service from AngularJS.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
This feature adds an `onUrlChange` to Angular's `Location` class. This is useful to track all updates coming from anywhere in the framework. Without this method, it's difficult (or impossible) to track updates run through `location.go()` or `location.replaceState()` as the browser doesn't publish events when `history.pushState()` or `.replaceState()` are run.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…ngular#30055)

When using the `history` API, setting a new `state` and retrieving it does not pass a `===` test to the object used to set the state. In other words, `history.state` is always a copy. This change makes the `MockPlatformLocation` behave in the same way.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…gular#30055)

This abstract class (and AngularJSUrlCodec) are used for serializing and deserializing pieces of a URL string. AngularJS had a different way of doing this than Angular, and using this class in conjunction with the LocationUpgradeService an application can have control over how AngularJS URLs are serialized and deserialized.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…gular#30055)

This commit provides a replacement for `$location`. The new service is written in Angular, and can be consumed into existing applications by using the downgraded version
of the provider.

Prior to this addition, applications upgrading from AngularJS to Angular could get into a situation where AngularJS wanted to control the URL, and would often parse or se
rialize the URL in a different way than Angular. Additionally, AngularJS was alerted to URL changes only through the `$digest` cycle. This provided a buggy feedback loop
from Angular to AngularJS.

With this new `LocationUpgradeProvider`, the `$location` methods and events are provided in Angular, and use Angular APIs to make updates to the URL. Additionally, change
s to the URL made by other parts of the Angular framework (such as the Router) will be listened for and will cause events to fire in AngularJS, but will no longer attempt
 to update the URL (since it was already updated by the Angular framework).

This centralizes URL reads and writes to Angular and should help provide an easier path to upgrading AngularJS applications to Angular.

PR Close angular#30055
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
BioPhoton pushed a commit to BioPhoton/angular that referenced this pull request May 21, 2019
…common (angular#30117)

Follow-up to angular#30055 to include @angular/common/upgrade in the npm package

Closes angular#30116

PR Close angular#30117
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
action: merge The PR is ready for merge by the caretaker area: common Issues related to APIs in the @angular/common package cla: yes target: major This PR is targeted for the next major release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants