Skip to content

Commit 5163e3d

Browse files
atscottalxhub
authored andcommitted
feat(router): Add UrlTree constructor to public API (angular#47186)
The `UrlTree` is a fundamental concept in the router's API design. Generally speaking, a `UrlTree` would be constructed via things like `Router.createUrlTree` or `UrlSerializer#parse`. The second example here is the core reason to make the constructor public, regardless of how develpers generally create a `UrlTree` in an application. Applications can provide their own `UrlSerializer` and may want to implement their own `parse` method. This means they would also need to create a `UrlTree` but would not be able to do so effectively because the constructor is marked `@internal`. In addition, the `UrlTree` constructor only has 3 parameters, all of which are already public. There's nothing "special" about it other than the potential desire to push developers to use other methods for constructing a `UrlTree` (i.e. `Router.createUrlTree`). Also see http://b/234604699#comment9 for additional context. PR Close angular#47186
1 parent daac137 commit 5163e3d

File tree

5 files changed

+21
-10
lines changed

5 files changed

+21
-10
lines changed

goldens/public-api/router/errors.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ export const enum RuntimeErrorCode {
1313
// (undocumented)
1414
INVALID_DOUBLE_DOTS = 4005,
1515
// (undocumented)
16+
INVALID_ROOT_URL_SEGMENT = 4015,
17+
// (undocumented)
1618
INVALID_ROUTE_CONFIG = 4014,
1719
// (undocumented)
1820
MISPLACED_OUTLETS_COMMAND = 4004,

goldens/public-api/router/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,10 @@ export abstract class UrlSerializer {
10331033

10341034
// @public
10351035
export class UrlTree {
1036+
constructor(
1037+
root?: UrlSegmentGroup,
1038+
queryParams?: Params,
1039+
fragment?: string | null);
10361040
fragment: string | null;
10371041
// (undocumented)
10381042
get queryParamMap(): ParamMap;

packages/router/src/errors.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ export const enum RuntimeErrorCode {
2525
OUTLET_NOT_ACTIVATED = 4012,
2626
OUTLET_ALREADY_ACTIVATED = 4013,
2727
INVALID_ROUTE_CONFIG = 4014,
28+
INVALID_ROOT_URL_SEGMENT = 4015,
2829
}

packages/router/src/router.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import {ChildrenOutletContexts} from './router_outlet_context';
3232
import {ActivatedRoute, ActivatedRouteSnapshot, createEmptyState, RouterState, RouterStateSnapshot} from './router_state';
3333
import {Params} from './shared';
3434
import {DefaultUrlHandlingStrategy, UrlHandlingStrategy} from './url_handling_strategy';
35-
import {containsTree, createEmptyUrlTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree';
35+
import {containsTree, IsActiveMatchOptions, isUrlTree, UrlSerializer, UrlTree} from './url_tree';
3636
import {flatten} from './utils/collection';
3737
import {standardizeConfig, validateConfig} from './utils/config';
3838
import {Checks, getAllRouteGuards} from './utils/preactivation';
@@ -582,7 +582,7 @@ export class Router {
582582
this.isNgZoneEnabled = ngZone instanceof NgZone && NgZone.isInAngularZone();
583583

584584
this.resetConfig(config);
585-
this.currentUrlTree = createEmptyUrlTree();
585+
this.currentUrlTree = new UrlTree();
586586
this.rawUrlTree = this.currentUrlTree;
587587
this.browserUrlTree = this.currentUrlTree;
588588

packages/router/src/url_tree.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,6 @@ import {equalArraysOrString, forEach, shallowEqual} from './utils/collection';
1414

1515
const NG_DEV_MODE = typeof ngDevMode === 'undefined' || ngDevMode;
1616

17-
export function createEmptyUrlTree() {
18-
return new UrlTree(new UrlSegmentGroup([], {}), {}, null);
19-
}
20-
2117
/**
2218
* A set of options which specify how to determine if a `UrlTree` is active, given the `UrlTree`
2319
* for the current router state.
@@ -196,14 +192,22 @@ export class UrlTree {
196192
// TODO(issue/24571): remove '!'.
197193
_queryParamMap!: ParamMap;
198194

199-
/** @internal */
200195
constructor(
201196
/** The root segment group of the URL tree */
202-
public root: UrlSegmentGroup,
197+
public root: UrlSegmentGroup = new UrlSegmentGroup([], {}),
203198
/** The query params of the URL */
204-
public queryParams: Params,
199+
public queryParams: Params = {},
205200
/** The fragment of the URL */
206-
public fragment: string|null) {}
201+
public fragment: string|null = null) {
202+
if (NG_DEV_MODE) {
203+
if (root.segments.length > 0) {
204+
throw new RuntimeError(
205+
RuntimeErrorCode.INVALID_ROOT_URL_SEGMENT,
206+
'The root `UrlSegmentGroup` should not contain `segments`. ' +
207+
'Instead, these segments belong in the `children` so they can be associated with a named outlet.');
208+
}
209+
}
210+
}
207211

208212
get queryParamMap(): ParamMap {
209213
if (!this._queryParamMap) {

0 commit comments

Comments
 (0)