Как получить параметры маршрутизатора при использовании pipe в сочетании с skipWhile? - PullRequest
0 голосов
/ 02 октября 2019

У меня есть динамическая навигация BreadCrumb, где мне нужно получить параметры из URL. Чтобы добиться этого, я выполняю следующий код:

const userId = this.activatedRoute.params
               .pipe(skipWhile((params: Params) => Number.isNaN(+params['userId'])));

const getAppUserId = userId.pipe(
            switchMap((params: Params) => {
                return +params['userId']
                    ? this.myAppService.getApplicationUser(+params['userId'])
                    : of('')
            }))

Но он всегда пуст и я никогда не передаю параметры в Observable. Когда я использую queryParams, он работает нормально, но я не хочу использовать концепцию queryParams. Есть идеи, где я ошибаюсь?

Ответы [ 3 ]

0 голосов
/ 02 октября 2019

Первый выпуск:

Number.isNaN(+params['userId'])

Возвращает строку, а не число.

Второй выпуск:

const getAppUserId = userId.pipe(
  switchMap((params: Params) => {

Вы получаете не параметры из наблюдаемого, а идентификатор пользователя (ну, на самом деле, логическое).

Если вы хотите "получить идентификатор параметра из / через наблюдаемый объект и после этого использовать его для: getAppUserId с switchMap, чтобы сделать HTTP-вызов с идентификатором параметра, который я получил из snapshot.params"

Тогда правильный код будет

this.activatedRoute.params.pipe(
  map(params => params.id),
  switchMap(userId => this.myAppService.getApplicationUser(userId)
);

Вы не должны проверять правильность идентификатора: URL-адреса являются строками, вы не можете доверять пользователю. Просто сделайте запрос, и если идентификатор ничего не соответствует, то ваш API ничего не вернет. Пусть API контролирует все идентификаторы, а не ваш клиент.

0 голосов
/ 07 октября 2019

Проблема решена. Было довольно просто ... исправление состояло в том, чтобы поймать параметр из route.snapshot.

this.router.events
        .pipe(filter(event => event instanceof NavigationEnd))
        .pipe(map(() => {return this.activatedRoute;}))
        .pipe(
            map((route) => {
                while (route.firstChild) {route = route.firstChild;}
                return route;
            })
        ).subscribe(route => {
             console.log(`param: ${route.snapshot.params['id']}`);
             ...
             ...
        });
0 голосов
/ 02 октября 2019

Однажды я создал автоматизированный конструктор хлебных крошек, который полагается только на статические данные в ваших маршрутах. Мне удалось найти его обратно, так что вот вам, на случай, если это поможет:

export class RouteBreadcrumbsComponent {

  breadcrumbs = [];

  constructor(
    private router: Router,
  ) {
    let buffer = [];

    /* 
       Listen for router events in reverse order (to get all events).
       From the snapshots, return its path and its breadcrumb.
    */
    this.router.events.pipe(
      filter(event => event instanceof ActivationEnd),
      map((event: ActivationEnd) => [
        event.snapshot.data && event.snapshot.data.crumb || undefined,
        this.determineCorrectPath(event.snapshot),
      ]),
      filter(([crumb, url]) => !!crumb),
    ).subscribe(([crumb, url]) => buffer.push({ crumb, url }));

    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd)
    ).subscribe(event => {
      this.breadcrumbs = buffer.reverse();
      buffer = [];
    });
  }

  determineCorrectPath(snapshot: ActivatedRouteSnapshot) {
    const path = snapshot.routeConfig.path;
    const params = snapshot.params;

    // Path = route with a param, so get the param
    if (path.startsWith(':'))
      return params[path.replace(':', '')];
    // Path = '' = route group or root route of a lazy loaded module, so take the parent path
    else if (!path)
      return snapshot.parent.routeConfig.path;
    // Path can be used as is
    else
      return path;
  }

  buildRoutingArray(crumbIndex: number) {
    return this.breadcrumbs
      .slice(0, crumbIndex + 1)
      .map(crumb => crumb.url)
      .join('/');
  }
}

Все, что вам нужно сделать, это предоставить data: { crumb: 'Your component crumb' } для каждого из ваших маршрутов, и оно должно работать.

...