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(router): add pathParamsOrQueryParamsChange mode for runGuardsAndResolvers #27464

Closed
wants to merge 1 commit into
base: master
from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file or symbol
Failed to load files and symbols.
+48 −5
Diff settings

Always

Just for now

feat(router): add pathParamsOrQueryParamsChange mode for runGuardsAnd…

…Resolvers

This option means guards and resolvers will ignore changes to matrix parameters. Guards and resolvers will be rerun when the path changes, when path parameters change, or when query parameters change.

The primary use case for such a mode is when updating the UI and getting the URL to be in sync with local changes. For example, if displaying a sortable table, changing the sort direction is often handled by the table itself. But you would want to update the URL to be in sync with what's being displayed to the user. As long as the table sort direction is stored as a matrix parameter, you can use this option to update the URL without causing the overhead of re-running guards and resolvers.

Related to #26861 #18253
  • Loading branch information...
jasonaden committed Dec 4, 2018
commit 6cf65394b19007d8dba5147257886baf74ffee53
Copy path View file
@@ -42,9 +42,11 @@ import {UrlSegment, UrlSegmentGroup} from './url_tree';
* mode ignores query param changes.
* - `paramsOrQueryParamsChange` - Guards and resolvers will run when any parameters change. This
* includes path, matrix, and query params.
* - `pathParamsChange` Run guards and resolvers path or any path params change. This mode is
* - `pathParamsChange` - Run guards and resolvers path or any path params change. This mode is
* useful if you want to ignore changes to all optional parameters such as query *and* matrix
* params.
* - `pathParamsOrQueryParamsChange` - Same as `pathParamsChange`, but also rerun when any query
* param changes
* - `always` - Run guards and resolvers on every navigation.
* - `children` is an array of child route definitions.
* - `loadChildren` is a reference to lazy loaded child routes. See `LoadChildren` for more
@@ -366,8 +368,8 @@ export type QueryParamsHandling = 'merge' | 'preserve' | '';
* See `Routes` for more details.
* @publicApi
*/
export type RunGuardsAndResolvers =
'pathParamsChange' | 'paramsChange' | 'paramsOrQueryParamsChange' | 'always';
export type RunGuardsAndResolvers = 'pathParamsChange' | 'pathParamsOrQueryParamsChange' |
'paramsChange' | 'paramsOrQueryParamsChange' | 'always';

/**
* See `Routes` for more details.
@@ -151,6 +151,10 @@ function shouldRunGuardsAndResolvers(
case 'pathParamsChange':
return !equalPath(curr.url, future.url);

case 'pathParamsOrQueryParamsChange':
return !equalPath(curr.url, future.url) ||
!shallowEqual(curr.queryParams, future.queryParams);

case 'always':
return true;

@@ -2375,7 +2375,8 @@ describe('Integration', () => {
expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}, {data: 3}, {data: 4}]);
})));

it('should not rerun guards and resolvers', fakeAsync(inject([Router], (router: Router) => {
it('should rerun rerun guards and resolvers when path params change',
fakeAsync(inject([Router], (router: Router) => {
const fixture = configureRouter(router, 'pathParamsChange');

const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance;
@@ -2448,6 +2449,42 @@ describe('Integration', () => {

expect(guardRunCount).toEqual(4);
})));

it('should rerun rerun guards and resolvers when path or query params change',
fakeAsync(inject([Router], (router: Router) => {
const fixture = configureRouter(router, 'pathParamsOrQueryParamsChange');

const cmp: RouteCmp = fixture.debugElement.children[1].componentInstance;
const recordedData: any[] = [];
cmp.route.data.subscribe((data: any) => recordedData.push(data));

// First navigation has already run
expect(guardRunCount).toEqual(1);
expect(recordedData).toEqual([{data: 0}]);

// Changing matrix params will not result in running guards or resolvers
router.navigateByUrl('/a;p=1');
advance(fixture);
expect(guardRunCount).toEqual(1);
expect(recordedData).toEqual([{data: 0}]);

router.navigateByUrl('/a;p=2');
advance(fixture);
expect(guardRunCount).toEqual(1);
expect(recordedData).toEqual([{data: 0}]);

// Adding query params will re-run guards/resolvers
router.navigateByUrl('/a;p=2?q=1');
advance(fixture);
expect(guardRunCount).toEqual(2);
expect(recordedData).toEqual([{data: 0}, {data: 1}]);

// Changing query params will re-run guards/resolvers
router.navigateByUrl('/a;p=2?q=2');
advance(fixture);
expect(guardRunCount).toEqual(3);
expect(recordedData).toEqual([{data: 0}, {data: 1}, {data: 2}]);
})));
});

describe('should wait for parent to complete', () => {
@@ -473,7 +473,7 @@ export declare class RoutesRecognized extends RouterEvent {
toString(): string;
}

export declare type RunGuardsAndResolvers = 'pathParamsChange' | 'paramsChange' | 'paramsOrQueryParamsChange' | 'always';
export declare type RunGuardsAndResolvers = 'pathParamsChange' | 'pathParamsOrQueryParamsChange' | 'paramsChange' | 'paramsOrQueryParamsChange' | 'always';

export declare class Scroll {
readonly anchor: string | null;
ProTip! Use n and p to navigate between commits in a pull request.