Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions goldens/public-api/router/index.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,11 @@ export type QueryParamsHandling = 'merge' | 'preserve' | 'replace' | '';

// @public
export class RedirectCommand extends Error {
constructor(redirectTo: UrlTree, navigationBehaviorOptions?: NavigationBehaviorOptions | undefined);
constructor(redirectTo: UrlTree | `/${string}`, navigationBehaviorOptions?: NavigationBehaviorOptions | undefined);
// (undocumented)
readonly navigationBehaviorOptions?: NavigationBehaviorOptions | undefined;
// (undocumented)
readonly redirectTo: UrlTree;
readonly redirectTo: UrlTree | `/${string}`;
}

// @public
Expand Down
2 changes: 1 addition & 1 deletion packages/router/src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export type GuardResult = boolean | UrlTree | RedirectCommand;
*/
export class RedirectCommand extends Error {
constructor(
readonly redirectTo: UrlTree,
readonly redirectTo: UrlTree | `/${string}`,
readonly navigationBehaviorOptions?: NavigationBehaviorOptions,
) {
super();
Expand Down
13 changes: 7 additions & 6 deletions packages/router/src/navigation_canceling_error.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,16 @@ export function redirectingNavigationError(
urlSerializer: UrlSerializer,
redirect: UrlTree | RedirectCommand,
): RedirectingNavigationCancelingError {
const {redirectTo, navigationBehaviorOptions} = isUrlTree(redirect)
? {redirectTo: redirect, navigationBehaviorOptions: undefined}
: redirect;
const target = isUrlTree(redirect) ? redirect : redirect.redirectTo;
const url = isUrlTree(target) ? target : urlSerializer.parse(target);
const error = navigationCancelingError(
ngDevMode && `Redirecting to "${urlSerializer.serialize(redirectTo)}"`,
ngDevMode && `Redirecting to "${urlSerializer.serialize(url)}"`,
NavigationCancellationCode.Redirect,
) as RedirectingNavigationCancelingError;
error.url = redirectTo;
error.navigationBehaviorOptions = navigationBehaviorOptions;
error.url = url;
error.navigationBehaviorOptions = isUrlTree(redirect)
? undefined
: redirect.navigationBehaviorOptions;
return error;
}

Expand Down
13 changes: 3 additions & 10 deletions packages/router/src/navigation_transition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -944,10 +944,8 @@ export class NavigationTransitions {
);

if (navigationErrorHandlerResult instanceof RedirectCommand) {
const {message, cancellationCode} = redirectingNavigationError(
this.urlSerializer,
navigationErrorHandlerResult,
);
const {url, message, cancellationCode, navigationBehaviorOptions} =
redirectingNavigationError(this.urlSerializer, navigationErrorHandlerResult);
this.events.next(
new NavigationCancel(
overallTransitionState.id,
Expand All @@ -956,12 +954,7 @@ export class NavigationTransitions {
cancellationCode,
),
);
this.events.next(
new RedirectRequest(
navigationErrorHandlerResult.redirectTo,
navigationErrorHandlerResult.navigationBehaviorOptions,
),
);
this.events.next(new RedirectRequest(url, navigationBehaviorOptions));
} else {
this.events.next(navigationError);
throw e;
Expand Down
24 changes: 24 additions & 0 deletions packages/router/test/integration/guards.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,30 @@ export function guardsIntegrationSuite() {
expect(location.path()).toEqual('/redirected');
expect(location.getState()).toEqual(jasmine.objectContaining({test: 1}));
});

it('can redirect with string URL', async () => {
TestBed.configureTestingModule({
providers: [provideRouter([])],
});
const router = TestBed.inject(Router);
const location = TestBed.inject(Location);
router.resetConfig([
{path: '', component: SimpleCmp},
{
path: 'one',
component: RouteCmp,
canActivate: [() => new RedirectCommand('/redirected')],
},
{path: 'redirected', component: SimpleCmp},
]);
const fixture = await createRoot(router, RootCmp);
router.navigateByUrl('/one');

await advance(fixture);

expect(location.path()).toEqual('/redirected');
expect(router.url.toString()).toEqual('/redirected');
});
});

it('can redirect to 404 without changing the URL', async () => {
Expand Down