Как перенаправить маршрут с некоторым идентификатором на понятный человеку URL и обработать канонический URL в маршрутах angular? - PullRequest
3 голосов
/ 02 марта 2020

У меня есть два формата URL

example.com/posts/:postId и example.com/posts/:postId/:postTitle точно так же как переполнение стека отдельных URL-адресов вопросов.

На angular маршруте мне нужно перенаправить все URL с :postId на :postId/:PostTitle или напрямую загрузить страницу с :postId/:PostTitle на ту же страницу.

post .module.ts

const routes: Routes = [
    {
        path: ':postId',
        resolve: {data: PdResolver}, 
        redirectTo: ':postId/:PostTitle', 
        pathMatch: 'full'
    },
    {
        path: ':postId/:PostTitle',
        component: PostComponent,
        data: {
            title: 'This has to be the post fetched title'
        }
    }
];
  • redirectTo: ':postId/:PostTitle': здесь у меня нет postTitle, поэтому он выдает ошибку
  • Как я могу добавить postTitle к URL а также избежать дублирования вопроса URL.
  • Какие рекомендации следует использовать по этой схеме.

У меня нет названия, поэтому сначала мне нужно получить postTitle с использованием postId, поэтому у нас есть преобразователь данных после публикации (PdResolver),

Обновление вопроса: Для обходного пути:

Я попытался с дочерним компонентом, который по крайней мере решает дело, но все еще задается вопросом, если я должен следовать этому подходу или нет.

    {
        path: ':postId',
        component: PostOutletComponent,
        resolve: {data: PdResolver},
        children: [
            {
                path: ':postTitle',
                component: PostComponent,
            }]

    }

И в PostOutletComponent я перемещаюсь дальше к дочернему компоненту после получения заголовка

PostOutletComponent.ts

static stripHtml(html: string) {
        let div = document.createElement('DIV');
        div.innerHTML = html;
        const cleanText = div.innerText;
        div = null;
        return cleanText;
    }

 ngOnInit() {
        this.reolveData = this._route.snapshot.data;
        let postTitle = PostOutletComponent.stripHtml(
            this.reolveData.data.data.post_title);
        postTitle = postTitle.replace(/\s+/g, '-').toLowerCase();
        this.router.navigate([postTitle], {relativeTo: this._route});
    }

1 Ответ

1 голос
/ 03 марта 2020

Я сделал Stackblitz на основе вашего кода: https://stackblitz.com/edit/angular-r1tvx2

Это решает проблему, которая возникает, если пользователь переходит на URL с существующим идентификатором, но с неправильным заголовком. В приведенном выше примере заголовок исправлен, как это делает переполнение стека.

Я сделал это, используя только один распознаватель и один класс компонентов. Resolver позаботится о перенаправлении на правильный URL. Обратите внимание, что Resolver помещен в более конкретный c маршрут с заголовком.

Конфигурация маршрута , порядок маршрутов важен, в первую очередь следует указать более конкретный c маршрут с title:

  {
    path: "posts/:id/:title",
    component: PostComponent,
    resolve: { somedata: PostDetailResolverService }
  },
  {
    path: "posts/:id",
    redirectTo: "posts/:id/title-to-be-repalced",
  },
  { path: "**", component: PageNotFoundComponent }
];

Resolver , перенаправляет на URL с правильным заголовком:

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<Somedata> | Observable<never> {
    let id = +route.paramMap.get("id");
    let title = route.paramMap.get("title");
    return this.getData(id).pipe(
      take(1),
      mergeMap(res => {
        if (res) {
          console.log("Resolver - Navigation continues to the route with data:", res);
          if (!title || title != res.title) {
            this.router.navigate(["posts/" + res.id + "/" + res.title]);
          } 
          return of(res);
        } else {
          // id not found
          console.log("Navigation cancelled");
          this.router.navigate([""]);
          return EMPTY;
        }
      })
    );
  }
...