javascript - How to reference query params in redirectTo - Stack Overflow

I would like to provide a path that redirects to a given page based on query parameters. For example:r

I would like to provide a path that redirects to a given page based on query parameters. For example:

/redirect?page=hero&id=1

should redirect to:

/hero/1

Is there any way to do this in the route config? Something like:

{ path: 'redirect?page&id', redirectTo: ':page/:id' }

I can get the redirectTo to respect path parameters but not query parameters. Any ideas?

I would like to provide a path that redirects to a given page based on query parameters. For example:

/redirect?page=hero&id=1

should redirect to:

/hero/1

Is there any way to do this in the route config? Something like:

{ path: 'redirect?page&id', redirectTo: ':page/:id' }

I can get the redirectTo to respect path parameters but not query parameters. Any ideas?

Share Improve this question edited Sep 10, 2024 at 13:12 times29 3,3733 gold badges25 silver badges43 bronze badges asked Jan 12, 2018 at 20:28 callmepillscallmepills 7229 silver badges13 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 2

You can try to use redirectTo: '/:page/:id' and provide extracted from your URL page and id values using custom UrlMatcher():

...

const appRoutes: Routes = [
  {
    path: 'hero/:id',
    ponent: TestComponent
  },
  {
    matcher: redirectMatcher,
    redirectTo: '/:page/:id'
  }
];

...

/**
 * custom url matcher for router config
 */
export function redirectMatcher(url: UrlSegment[]) {
  if (url[0] && url[0].path.includes('redirect')) {
    const path = url[0].path;
    // sanity check
    if (path.includes('page') && path.includes('id')) {
      return {
        consumed: url,
        posParams: {
          page: new UrlSegment(path.match(/page=([^&]*)/)[1], {}),
          id: new UrlSegment(path.match(/id=([^&]*)/)[1], {})
        }
      }
    }
  }
  return null;
}

STACKBLITZ: https://stackblitz./edit/angular-t3tsak?file=app%2Ftest.ponent.ts

There is another issue when using redirectTo: ..., active link is not updated, actually isActive flag is not set to true, it is seen on my stackblitz when acrive redirection links are not colored in red

No, there is no way of doing it by a configuration. YOu see, Angular's router does not explicitly define query parameters - any url can have an arbitrary number of query params, and the paths '/page/id' and '/page/id?key=value' are treated as the same in Angular and do map to the same ponent. There are other, more cumbersome workarounds. One is to create a dummy ponent and redirect based on ActivatedRoute.queryParams Observable from the ponent's ngOnInit method. You can easily see why this is a bad idea. Another way is to create a resolver, this way you maybe can dismiss the ponent declaration and just redirect from the resolver, again, based on the ActivatedRoute.queryParams Observable, which seems cleaner.

But I do not really get why one would need such a route in a front end application, if you want someone to visit '/page/id', then just navigate them to the page, without any intermediary tricks.

Angular >= 18

With Angular 18 you can use a RedirectFunction. A route config like this should do the trick:

{
  path: 'redirect',
  redirectTo: route => `/${route.queryParams.page}/${route.queryParams.id}`
}

Angular < 18

You can solve it with a CanActivateFn:

import { CanActivateFn, ParamMap, Router } from '@angular/router';
import { inject } from '@angular/core';
import { from } from 'rxjs';

export const redirectTo =
    (redirectToUrl: (params: ParamMap) => string): CanActivateFn =>
    route =>
        from(inject(Router).navigateByUrl(redirectToUrl(route.queryParamMap)));

Then your route config:

{
  path: 'redirect',
  canActivate: [redirectTo(params => `/${params.get('page')}/${params.get('id')}`)],
  children: []
}

Additional bonus - a Jest test for the CanActivateFn:

import { TestBed } from '@angular/core/testing';
import { ActivatedRouteSnapshot, CanActivateFn, convertToParamMap, ParamMap, Router, RouterStateSnapshot } from '@angular/router';

import { redirectTo } from './redirect-to';

const redirectToUrl = (params: ParamMap) => `/${params.get('page')}/${params.get('id')}`;

describe('redirectWhileKeepingQueryParams', () => {
    const executeGuard: CanActivateFn = (...guardParameters) =>
        TestBed.runInInjectionContext(() => redirectTo(redirectToUrl)(...guardParameters));

    beforeEach(() => {
        TestBed.configureTestingModule({});
    });

    it('should be created', () => {
        expect(executeGuard).toBeTruthy();
    });

    it('should redirect to the given route', () => {
        // Arrange
        const navigateByUrlSpy = jest.spyOn(TestBed.inject(Router), 'navigateByUrl');
        const page = 'hero';
        const id = 1;
        const route = { queryParamMap: convertToParamMap({ page, id }) } as Partial<ActivatedRouteSnapshot> as ActivatedRouteSnapshot;
        const state = {} as RouterStateSnapshot;

        // Act
        executeGuard(route, state);

        // Assert
        expect(navigateByUrlSpy).toHaveBeenCalledWith(`/${page}/${id}`);
    });
});
this.router.navigate(['/inform/page'], { queryParams: { munity: 970 } });

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1742371189a4431298.html

相关推荐

  • javascript - How to reference query params in redirectTo - Stack Overflow

    I would like to provide a path that redirects to a given page based on query parameters. For example:r

    7小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信