web-dev-qa-db-fra.com

Angular 2 paramètre d'itinéraire optionnel

Est-il possible d'avoir un paramètre de route facultatif dans la route Angular 2? J'ai essayé la syntaxe Angular 1.x dans RouteConfig mais j'ai reçu l'erreur suivante:

"EXCEPTION ORIGINALE: chemin"/utilisateur /: id? "Contient"? ", Ce qui n'est pas autorisé dans une configuration de route."

@RouteConfig([
{
    path: '/user/:id?',
    component: User,
    as: 'User'
}])
131
Jeroen

Vous pouvez définir plusieurs itinéraires avec et sans paramètre:

@RouteConfig([
    { path: '/user/:id', component: User, name: 'User' },
    { path: '/user', component: User, name: 'Usernew' }
])

et gérez le paramètre optionnel dans votre composant:

constructor(params: RouteParams) {
    var paramId = params.get("id");

    if (paramId) {
        ...
    }
}

Voir également le problème lié à github: https://github.com/angular/angular/issues/3525

233
rerezz
{path: 'users', redirectTo: 'users/'},
{path: 'users/:userId', component: UserComponent}

De cette manière, le composant n'est pas rendu à nouveau lorsque le paramètre est ajouté.

46
Martin Cremer

Il est recommandé d'utiliser un paramètre de requête lorsque les informations sont facultatives.

Paramètres de route ou paramètres de requête?

Il n'y a pas de règle absolue. En général,

préférez un paramètre de route lorsque

  • la valeur est requise.
  • la valeur est nécessaire pour distinguer un chemin d'itinéraire d'un autre.

préférez un paramètre de requête lorsque

  • la valeur est optionnelle.
  • la valeur est complexe et/ou multi-variable.

à partir de https://angular.io/guide/router#optional-route-parameters

Vous devez simplement extraire le paramètre du chemin de la route.

@RouteConfig([
{
    path: '/user/',
    component: User,
    as: 'User'
}])
35
Jp_

Angular 4 - Solution pour traiter la commande du paramètre optionnel:

FAIRE CELA:

const appRoutes: Routes = [
  {path: '', component: HomeComponent},
  {path: 'products', component: ProductsComponent},
  {path: 'products/:id', component: ProductsComponent}
]

Notez que les routes products et products/:id portent exactement le même nom. Angular 4 suivra correctement products pour les itinéraires sans paramètre, et s'il s'agit d'un paramètre, il suivra products/:id.

Cependant, le chemin pour la route non paramétrique products doit pas avoir une barre oblique finale, sinon angular ne le traitera pas correctement comme un chemin de paramètre. Donc dans mon cas, j'avais le slash final pour les produits et cela ne fonctionnait pas.

NE FAITES PAS CELA:

...
{path: 'products/', component: ProductsComponent},
{path: 'products/:id', component: ProductsComponent},
...
17
ObjectiveTC

la réponse de rerezz est jolie, mais elle a un grave défaut. Cela force le composant User à réexécuter la méthode ngOnInit.

Cela peut être problématique lorsque vous faites des choses lourdes là-bas et que vous ne voulez pas que cela soit refait lorsque vous passez de la voie non paramétrique à la voie paramétrique. Bien que ces deux routes visent à imiter un paramètre d'URL facultatif, ne devenez pas deux routes distinctes.

Voici ce que je suggère pour résoudre le problème:

const routes = [
  {
    path: '/user',
    component: User,
    children: [
      { path: ':id', component: UserWithParam, name: 'Usernew' }
    ]
  }
];

Ensuite, vous pouvez déplacer la logique responsable de la gestion du paramètre vers le composant UserWithParam et laisser la logique base dans le composant User. Quoi que vous fassiez dans User::ngOnInit ne sera plus exécuté si vous naviguez de / user à / user/12.

N'oubliez pas de mettre le <router-outlet></router-outlet> dans le modèle de User.

9
matewka

Avec angular4, nous avons juste besoin d’organiser les itinéraires ensemble dans la hiérarchie

const appRoutes: Routes = [
  { path: '', component: MainPageComponent },
  { path: 'car/details', component: CarDetailsComponent },
  { 
    path: 'car/details/platforms-products', 
    component: CarProductsComponent 
  },
  { path: 'car/details/:id', component: CadDetailsComponent },
  { 
    path: 'car/details/:id/platforms-products', 
    component: CarProductsComponent 
  }
];

Cela fonctionne pour moi. De cette façon, le routeur sait quelle est la prochaine route en fonction des paramètres d’option id.

4
Ravi Jadhav

Couru dans une autre instance de ce problème, et en cherchant une solution à celui-ci est venu ici. Mon problème était que je faisais les enfants et que je chargeais les composants paresseux afin d'optimiser un peu les choses. En bref si vous êtes paresseux en chargeant le module parent. La chose principale était que j'utilisais '/: id' dans la route, et il se plaignait du fait que '/' en fasse partie. Pas le problème exact ici, mais cela s’applique.

App-routage depuis le parent

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: 'pathOne',
        loadChildren: 'app/views/$MODULE_PATH.module#PathOneModule'
      },
      {
        path: 'pathTwo',
        loadChildren: 'app/views/$MODULE_PATH.module#PathTwoModule'
      },
...

Itinéraires enfants paresseux chargés

...
const routes: Routes = [
  {
    path: '',
    children: [
      {
        path: '',
        component: OverviewComponent
      },
      {
        path: ':id',
        component: DetailedComponent
      },
    ]
  }
];
...
1
L.P.

Les réponses suggérées ici, y compris le réponse acceptée de rerezz , qui suggèrent d'ajouter plusieurs entrées de route, fonctionnent bien.

Toutefois, le composant sera recréé lors du changement entre les entrées de route, c'est-à-dire entre l'entrée de route avec le paramètre et l'entrée sans le paramètre.

Si vous voulez éviter cela, vous pouvez créer votre propre outil de routage d'itinéraires qui correspondra aux deux itinéraires:

export function userPageMatcher(segments: UrlSegment[]): UrlMatchResult {
    if (segments.length > 0 && segments[0].path === 'user') {
        if (segments.length === 1) {
            return {
                consumed: segments,
                posParams: {},
            };
        }
        if (segments.length === 2) {
            return {
                consumed: segments,
                posParams: { id: segments[1] },
            };
        }
        return <UrlMatchResult>(null as any);
    }
    return <UrlMatchResult>(null as any);
 }

Puis utilisez le matcher dans votre config de route:

const routes: Routes = [
    {
        matcher: userPageMatcher,
        component: User,
    }
];
1
Wayne Maurer

Je ne peux pas commenter, mais en référence à: paramètre de route optionnel Angular 2

une mise à jour pour Angular 6:

import {map} from "rxjs/operators"

constructor(route: ActivatedRoute) {
  let paramId = route.params.pipe(map(p => p.id));

  if (paramId) {
    ...
  }
}

Voir https://angular.io/api/router/ActivatedRoute pour plus d'informations sur le routage Angular6.

0
mschreib28

Face à un problème similaire avec le chargement paresseux, j’ai fait ceci:

const routes: Routes = [
  {
    path: 'users',
    redirectTo: 'users/',
    pathMatch: 'full'
  },
  {
    path: 'users',
    loadChildren: './users/users.module#UserssModule',
    runGuardsAndResolvers: 'always'
  },
[...]

Et puis dans le composant:

  ngOnInit() {
    this.activatedRoute.paramMap.pipe(
      switchMap(
        (params: ParamMap) => {
          let id: string = params.get('id');
          if (id == "") {
            return of(undefined);
          }
          return this.usersService.getUser(Number(params.get('id')));
        }
      )
    ).subscribe(user => this.selectedUser = user);
  }

Par ici:

  • L'itinéraire sans / est redirigé vers l'itinéraire avec. En raison du pathMatch: 'full', seul cet itinéraire complet spécifique est redirigé.

  • Ensuite, users/:id est reçu. Si la route réelle était users/, id est "", vérifiez-le dans ngOnInit et agissez en conséquence; sinon, id est l'identifiant et continue.

  • Le reste du composant agit sur selectedUser est ou non indéfini (* ngIf et les choses comme ça).

0
Javier Sedano