Angular 4 маршрутизация: возможно ли добавить ограничения к параметрам маршрута? - PullRequest
0 голосов
/ 04 февраля 2019

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

Например:

/ en / xxx

/ fr / xxx

/ru / yyy

/ fr / yyy

Поскольку я хочу использовать этот параметр, я добавил следующий маршрут

{ path: ':lang',  children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}

Проблема в том, что все совпадает: lang.

Например:

/ abc / xxx

Я хотел бы добавить к этому ограничения, чтобы я мог сказать, что: lang может быть только типа <'nl'|'fr' |'en' |'de'>.

Теперь, когда я хочу перейти в /robots.txt (который должен показать мне файл robots.txt), он отображается на: lang и отправляет меня в "/robots.txt/xxx"

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

Я попытался добавить файл robots.txt выше, но так как это файл ресурсов, я нене знаю, как показать это, добавив строку в файл rout.ts.

Я попытался добавить исключение в охрану маршрута, но затем я не могу перенаправить в robots.txt, так как он просто отображаетв параметре: lang.

Это мой текущий файл rout.ts:

{path: '', redirectTo: '/xxx', pathMatch: 'full', canActivate: [LangGuard]},
{path: 'xxx', component: xxx, canActivate: [LangGuard]},
{path: 'yyy', component: yyy, canActivate: [LangGuard]},
{ path: ':lang', canActivate: [LangGuard], children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}

Мой LangGuard довольно обширный, но плохо записывает короткую версию:

Get route parameters
If parameter is "nl", "fr", "de" or "en"
then return true //do nothing
else router.navigate('/' + decideLanguage() + state.url) // redirect to new url

Может быть, небольшой обзор того, чего я хочу достичь и что я получаю:

Что я хочу

/ -> /en/xxx
/abc -> /en/xxx
/xxx -> /en/xxx
/yyy -> /en/yyy

/en/xxx -> ok
/fr/xxx -> ok
/de/xxx -> ok

/en/abc -> notfound

/abc/xxx -> notfound
/abc/yyy -> notfound


/robots.txt -> ok

Что у меня есть

/ -> /en/xxx
/abc -> /en/xxx
/xxx -> /en/xxx
/yyy -> /en/yyy

/en/xxx -> ok
/fr/xxx -> ok
/de/xxx -> ok

/en/abc -> notfound

/abc/xxx -> ok (WRONG)
/abc/yyy -> ok (WRONG)


/robots.txt -> /robots.txt/xxx (WRONG)

ПРИМЕЧАНИЕ:Я не могу использовать redirectTo для языка, потому что язык выбран в соответствии с местным хранилищем, поэтому я используюхранитель маршрута

Если мне нужно добавить дополнительную информацию или у вас есть вопросы, не стесняйтесь их задавать, и я отвечу на них в меру своих возможностей.

Спасибо

Ответы [ 3 ]

0 голосов
/ 04 февраля 2019

Я бы попробовал Angular UrlMatcher .С этим вы можете определить свою собственную функцию сопоставления URL.ИМХО Охранники больше предназначены для проверки подлинности, а не для проверки правильности маршрута.

Вот пример :

Маршрутизация

export function checkLang(url: UrlSegment[]) {
  return url[0].path.startsWith('en') || url[0].path.startsWith('fr') || url[0].path.startsWith('de') || url[0].path.startsWith('nl') ? ({consumed: url}) : null;
}

export const routes = [  matcher: checkLang, component: TestComponent, children: [
      {path: '', redirectTo: 'xxx', pathMatch: 'full'},
      {path: 'xxx', component: x},
      {path: 'yyy', component: y}
]}]

, а затем TestComponent

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';

@Component({
  selector: 'app-test',
  template: '<div>HELLO</div>'
})
export class TestComponent implements OnInit {

  constructor(
    public route: ActivatedRoute,
    public router: Router
  ) { }


  ngOnInit() {
    console.log('LANGUAGE: ' + this.route.snapshot.url[0].path); // here you get the language and you can act consequently 
  }
}
0 голосов
/ 21 июля 2019

Выбранный ответ служит этой цели, стоит отметить, что он недостаточно гибок, если у вас есть пользовательский компонент, например, для языка, который не найден.Если только это не звук и не возможно перемещаться изнутри соответствующей функции, в которой я сомневаюсь.Я думаю, что в этом случае идеальным вариантом будет наличие компонента контейнера, просто чтобы выполнить проверку, иначе выберите соответствие: lang с остальными, загруженными как дочерние элементы.

Маршрутизация

{
    path: ':lang',
        component: LanguageContainerComponent,
            children: [
                {
      { path: '', redirectTo: 'xxx', pathMatch: 'full' },
                { path: 'xxx', component: x },
                { path: 'yyy', component: y }
      }
    ]
},
{ path: 'languagenotfound', component: LanguageNotFoundComponent },

Компонент

 import { Component, OnInit } from '@angular/core';
    import { ActivatedRoute, Router } from '@angular/router';

    @Component({
        selector: 'app-language-container',
        template: '<router-outlet></router-outlet>'
    })
    export class LanguageContainerComponent implements OnInit {

        constructor(
            public route: ActivatedRoute,
            public router: Router
        ) { }


        ngOnInit() {
            // Do your checks here
            //  if fail
            this.router.navigate(['languagenotfound']);
        }
    }

Если вы используете библиотеку, такую ​​как ngx-translate, можно внедрить

private translate: TranslateService

и использовать

this.translate.getLangs().includes(langParam)

, поскольку я не думаю, что вы можете внедрить службыв UrlMatcher

0 голосов
/ 04 февраля 2019

Вы можете использовать canActivate охранник и использовать его, чтобы программно установить, что параметр маршрута lang является одним из четырех языков, которые вы упомянули.

...