Parametro percorso opzionale 2 angolare


180

È possibile avere un parametro di rotta opzionale nella rotta Angolare 2? Ho provato la sintassi Angular 1.x in RouteConfig ma ho ricevuto l'errore seguente:

"ECCEZIONE ORIGINALE: Percorso" / utente /: id? "Contiene"? "Che non è consentito in una configurazione di percorso."

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

Risposte:


298

È possibile definire più percorsi con e senza parametro:

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

e gestisci il parametro opzionale nel tuo componente:

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

    if (paramId) {
        ...
    }
}

Vedi anche il relativo problema github: https://github.com/angular/angular/issues/3525


11
Correggimi se sbaglio, ma questa soluzione ha funzionato per me solo quando l'ordine delle route nell'array è stato invertito, ovvero la route con il parametro si è verificata prima dell'altra. Fino a quando non l'ho fatto, il router ha abbinato solo il percorso senza il parametro.
Aviad P.

10
questa soluzione si applica ancora? Ho notato che passare da "Utente" a "Utente nuovo" riporterà all'istante il componente "Utente"
teleaziz,

19
vecchio ma un grosso problema con questo approccio è che ogni percorso è trattato come un percorso unico e rende impossibile il riutilizzo dei componenti.
Agonia,

4
Come notato da @teleaziz, l'aggiunta del parametro renderà nuovamente il componente. Per evitare ciò, la risposta di Martin Cremer; l'aggiunta di una radice "redirectTo" con un valore di parametro vuoto, ha funzionato alla grande per me: stackoverflow.com/a/49159166/1364650 - ma è abbastanza confuso, penso che dovrebbero semplicemente supportare correttamente i parametri di route opzionali.
Vincent Sels,

2
Per coloro che si chiedono perché RouteParamsnon importare nel componente controllare questo: stackoverflow.com/a/36792261/806202 . La soluzione è utilizzare ActivatedRoute:route.snapshot.params['routeParam']
Arsen Khachaturyan,

89
{path: 'users', redirectTo: 'users/', pathMatch: 'full'},
{path: 'users/:userId', component: UserComponent}

In questo modo il componente non viene ridistribuito quando viene aggiunto il parametro.


6
Questa risposta è la migliore. Non esegue nuovamente il rendering dello stesso componente e non richiede più componenti.
Rex

4
La risposta migliore, ma ho aggiunto pathMatch: 'full'al reindirizzamento, altrimenti users/adminnel mio caso vengono reindirizzati percorsi come
Valeriy Katkov

4
Questa risposta è la migliore solo se stai bene con barre rovesciate sui tuoi URL come visualizzate nel browser. Considera forse un valore che rappresenta "un ID indefinito", ad esempio , /users/alloppure /users/homeleggi "tutto" o "home" come il ide semplicemente ignoralo se corrisponde al tuo valore magico. Quindi la prima riga sopra diventa redirectTo: 'users/home'o qualunque cosa tu decida. Per me una barra finale si distingue davvero come qualcosa che non va.
Simon_Weaver,

@Simon_Weaver Sono d'accordo. Ho trovato un'altra soluzione utilizzando un matcher che non presenta questo problema: stackoverflow.com/a/56391974/664533
Wayne Maurer

1
è un incantesimo semplice ma abbastanza indistruttibile: D La migliore soluzione!
Verri,

45

Si consiglia di utilizzare un parametro di query quando le informazioni sono facoltative.

Instradare parametri o parametri query?

Non c'è una regola dura e veloce. In generale,

preferisce un parametro di rotta quando

  • il valore è richiesto.
  • il valore è necessario per distinguere un percorso da un altro.

preferisce un parametro di query quando

  • il valore è facoltativo.
  • il valore è complesso e / o multi-variabile.

da https://angular.io/guide/router#optional-route-parameters

Devi solo eliminare il parametro dal percorso.

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

6
La modifica dei parametri di route facoltativi restituisce i componenti, ma la modifica di queryParams no. Inoltre, se si risolvono alcuni dati prima della navigazione del percorso, verranno richiesti ogni volta che si modificano parametri di percorso opzionali.
Rakhat,

1
Cordiali saluti, quel collegamento di ancoraggio non funziona più. Il nuovo link sembra essere Parametri del percorso: obbligatorio o facoltativo?
spottedmahn,

20

Angolare 4 - Soluzione per indirizzare l'ordinamento del parametro opzionale:

FAI QUESTO:

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

Si noti che i percorsi productse products/:idsono nominati esattamente allo stesso modo. L'angolo 4 seguirà correttamente productsper le rotte senza parametri e se seguirà un parametro products/:id.

Tuttavia, il percorso per la rotta non parametrica nonproducts deve avere una barra finale, altrimenti angolare lo tratterà erroneamente come una traccia parametro. Quindi nel mio caso, ho avuto la barra finale per i prodotti e non funzionava.

NON FARE QUESTO:

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

Se entrambi stanno andando al ProductComponent, come gestisci il parametro opzionale lì?
Arwin,

1
Puoi accedere ai parametri: id1,: id2, ecc così come all'URL richiesto in ProductsComponent in questo modo: this.route.url.first () .mergeMap ((url) => {// console.log ('1: modifica url rilevata '+ url); restituisce this.route.params.do ((params) => {// console.log (' 2: url + modifica parametri rilevati '+ params ["id1"] +' '+ params ["id2"]); this.id1 = params ["id1"]; this.id2 = params ["id2"];})})
ObjectiveTC

2
Ricorda che puoi passare anche dataal componente, che può essere diverso per ogni percorso anche allo stesso componente. È {path: 'products', component: ProductsComponent, data: { showAllProducts: true} },possibile utilizzare l'esempio e quindi verificare showAllProducts. Un po 'più bello quindi verificare un valore nullo, ma per casi più semplici probabilmente va bene.
Simon_Weaver,

1
Sfortunatamente, questa soluzione impedisce ad Angular di riutilizzare il componente tra prodotti e prodotti /: id. Il componente verrà ripristinato.
Kodiak,

@Kodiak - Non credo sia corretto. La mia comprensione è che in app.module.ts, il ProductComponent viene istanziato una volta e che il motore angolare riutilizza quindi il Component Products istanziato su ogni evento navigabile (prodotti e prodotti /: id ecc). Puoi spiegare o dimostrare in che modo ProductsComponent potrebbe essere una nuova istanza nel codice sopra e come potresti prevenire la nuova istanza?
ObjectiveTC

11

la risposta di rerezz è piuttosto carina ma ha un grave difetto. Fa Usereseguire nuovamente il ngOnInitmetodo al componente.

Potrebbe essere problematico quando fai delle cose pesanti lì e non vuoi che venga ripetuto quando passi dalla rotta non parametrica a quella parametrica. Sebbene queste due route abbiano lo scopo di imitare un parametro url opzionale, non diventano 2 route separate.

Ecco cosa suggerisco di risolvere il problema:

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

Quindi è possibile spostare la logica responsabile della gestione del parametro sul UserWithParamcomponente e lasciare la logica di base nel Usercomponente. Qualunque cosa tu faccia User::ngOnInitnon verrà eseguita di nuovo quando navighi da / utente a / utente / 123 .

Non dimenticate di mettere il <router-outlet></router-outlet>nel Usermodello 's.


Evitare che il componente venga ricreato è una buona cosa se le prestazioni sono fondamentali. Ho un'altra soluzione che evita anche che il componente venga ricreato: stackoverflow.com/a/56391974/664533
Wayne Maurer

4

Le risposte suggerite qui, inclusa la risposta accettata da rerezz che suggeriscono di aggiungere più voci di percorso, funzionano bene.

Tuttavia, il componente verrà ricreato quando si cambia tra le voci della rotta, ovvero tra la voce della rotta con il parametro e la voce senza il parametro.

Se vuoi evitarlo, puoi creare il tuo abbinamento percorsi che corrisponderà a entrambi i percorsi:

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);
 }

Quindi utilizzare il matcher nella configurazione del percorso:

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

@KevinBeal Ho implementato parecchi matcher che funzionano con AOT. Qual è l'errore che stai ricevendo qui?
Wayne Maurer,

Ops. Era qualcos'altro. Il mio abbinamento funziona con AOT.
Kevin Beal,

questo è un po 'complicato ma la migliore soluzione a questo problema
fedor.belov

4

Con angular4 dobbiamo solo organizzare i percorsi insieme in gerarchia

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 
  }
];

Questo funziona per me. In questo modo il router sa quale sarà il prossimo percorso in base ai parametri dell'ID opzione.


1

Sono andato in un'altra istanza di questo problema e nella ricerca di una soluzione è venuto qui. Il mio problema era che stavo facendo i bambini, e anche il caricamento lento dei componenti per ottimizzare un po 'le cose. In breve, se sei pigro nel caricare il modulo genitore. La cosa principale era che usavo "/: id" nel percorso, e si lamenta del fatto che "/" ne faccia parte. Non è il problema esatto qui, ma si applica.

Instradamento delle app dal genitore

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

Percorsi figlio pigri caricati

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


0

Di fronte a un problema simile con caricamento lento ho fatto questo:

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

E poi nel componente:

  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);
  }

Per di qua:

  • Il percorso senza /viene reindirizzato al percorso con. A causa di pathMatch: 'full', viene reindirizzato solo tale percorso completo specifico.

  • Quindi, users/:idviene ricevuto. Se il percorso effettivo era users/, idè "", quindi registralo ngOnInite agisci di conseguenza; altrimenti, idè l'id e procedi.

  • Il resto del componect agisce su selectedUsernon è definito (* ngIf e cose del genere).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.