Parameter rute opsional sudut 2

180

Apakah mungkin untuk memiliki parameter rute opsional di rute Angular 2? Saya mencoba sintaks Angular 1.x di RouteConfig tetapi menerima kesalahan di bawah ini:

"PENGECUALIAN ASLI: Jalur" / user /: id? "Berisi"? "Yang tidak diizinkan dalam konfigurasi rute."

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

Jawaban:

298

Anda dapat menentukan beberapa rute dengan dan tanpa parameter:

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

dan menangani parameter opsional di komponen Anda:

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

    if (paramId) {
        ...
    }
}

Lihat juga masalah github terkait: https://github.com/angular/angular/issues/3525

rerezz
sumber
11
Perbaiki saya jika saya salah, tetapi solusi ini hanya berfungsi untuk saya ketika urutan rute dalam array terbalik, yaitu rute dengan parameter terjadi sebelum yang lain. Sampai saya melakukan itu, router hanya cocok dengan rute tanpa parameter.
Aviad P.
10
apakah solusi ini masih berlaku? Saya perhatikan pindah dari "Pengguna" ke "UserNew" akan instantiate komponen 'Pengguna'
teleaziz
19
tua tapi masalah utama dengan pendekatan ini adalah bahwa setiap rute diperlakukan sebagai rute unik dan itu membuat penggunaan kembali komponen tidak mungkin.
Penderitaan
4
Seperti dicatat oleh @teleaziz, menambahkan parameter akan membuat ulang komponen. Untuk menghindari ini, jawaban Martin Cremer; menambahkan 'redirectTo' root dengan nilai parameter kosong, bekerja sangat baik untuk saya: stackoverflow.com/a/49159166/1364650 - tapi itu cukup gila, saya pikir mereka hanya perlu mendukung parameter rute opsional dengan benar.
Vincent Sels
2
Bagi mereka yang bertanya-tanya mengapa RouteParamstidak mengimpor ke komponen, periksa ini: stackoverflow.com/a/36792261/806202 . Solusinya adalah dengan menggunakan ActivatedRoute:route.snapshot.params['routeParam']
Arsen Khachaturyan
89
{path: 'users', redirectTo: 'users/', pathMatch: 'full'},
{path: 'users/:userId', component: UserComponent}

Dengan cara ini komponen tidak dirender ulang ketika parameter ditambahkan.

Martin Cremer
sumber
6
Jawaban ini adalah yang terbaik. Itu tidak merender ulang komponen yang sama dan tidak memerlukan banyak komponen.
Rex
4
Jawaban terbaik, tetapi saya menambahkan pathMatch: 'full'untuk mengarahkan ulang, jika tidak jalur seperti users/adminjuga diarahkan dalam kasus saya
Valeriy Katkov
4
Jawaban ini hanya yang terbaik jika Anda setuju dengan garis miring pada URL Anda seperti yang terlihat di browser. Pertimbangkan mungkin nilai yang mewakili 'id tidak terdefinisi', misalnya /users/allatau /users/home, baca 'semua' atau 'rumah' sebagai iddan abaikan saja jika itu cocok dengan nilai ajaib Anda. Maka baris pertama di atas menjadi redirectTo: 'users/home'atau apa pun yang Anda putuskan. Bagi saya garis miring sangat menonjol sebagai sesuatu yang salah.
Simon_Weaver
@Simon_Weaver saya setuju. Saya menemukan solusi lain menggunakan korek api yang tidak memiliki masalah ini: stackoverflow.com/a/56391974/664533
Wayne Maurer
1
ini mantra yang sederhana tetapi tidak bisa dipecahkan: D Solusi terbaik!
Verri
45

Dianjurkan untuk menggunakan parameter kueri ketika informasi tersebut opsional.

Parameter Rute atau Parameter Kueri?

Tidak ada aturan yang keras dan cepat. Secara umum,

lebih suka parameter rute saat

  • nilai diperlukan.
  • nilai diperlukan untuk membedakan satu jalur rute dari yang lain.

lebih suka parameter kueri saat

  • nilainya opsional.
  • nilainya kompleks dan / atau multi-variate.

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

Anda hanya perlu mengambil parameter dari jalur rute.

@RouteConfig([
{
    path: '/user/',
    component: User,
    as: 'User'
}])
Jp_
sumber
6
Mengubah komponen rute parar rerenders opsional, tetapi mengubah queryParams tidak. Juga jika Anda menyelesaikan beberapa data sebelum navigasi rute, itu akan diminta setiap kali ketika Anda mengubah parameter rute opsional.
Rakhat
1
FYI, tautan jangkar itu tidak berfungsi lagi. Tautan baru tampaknya Parameter Rute: Diperlukan atau opsional?
spottedmahn
20

Angular 4 - Solusi untuk mengatasi pemesanan parameter opsional:

MELAKUKAN HAL INI:

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

Perhatikan bahwa productsdan products/:idrute diberi nama yang persis sama. Sudut 4 akan mengikuti dengan benar productsuntuk rute tanpa parameter, dan jika parameter itu akan mengikuti products/:id.

Namun, jalur untuk rute non-parameter tidakproducts boleh memiliki garis miring, jika tidak, sudut akan memperlakukannya sebagai jalur-parameter. Jadi dalam kasus saya, saya memiliki garis miring untuk produk dan itu tidak berhasil.

JANGAN LAKUKAN INI:

...
{path: 'products/', component: ProductsComponent},
{path: 'products/:id', component: ProductsComponent},
...
ObjectiveTC
sumber
Jika keduanya menuju ke ProductsComponent, bagaimana Anda menangani parameter opsional di sana?
Arwin
1
Anda dapat mengakses parameter: id1,: id2, dll, serta url yang diminta di ProductsComponent seperti: this.route.url.first () .mergeMap ((url) => {// console.log ('1: perubahan url terdeteksi '+ url); kembalikan this.route.params.do ((params) => {// console.log (' 2: perubahan url + params terdeteksi '+ params ["id1"] +' '+ params ["id2"]); this.id1 = params ["id1"]; this.id2 = params ["id2"];})})
ObjectiveTC
2
Ingat Anda juga dapat beralih datake komponen, yang dapat berbeda untuk setiap rute bahkan ke komponen yang sama. Contoh {path: 'products', component: ProductsComponent, data: { showAllProducts: true} },dapat digunakan dan kemudian Anda memeriksa showAllProducts. Sedikit lebih baik daripada memeriksa null, tetapi untuk kasus yang lebih sederhana mungkin baik-baik saja.
Simon_Weaver
1
Sayangnya, solusi ini akan mencegah Angular menggunakan kembali komponen antara produk dan produk /: id. Komponen akan di-instanciated.
Kodiak
@ Kodak - Saya tidak percaya itu benar. Pemahaman saya adalah bahwa di app.module.ts, ProductsComponent adalah instantiated satu kali, dan bahwa mesin sudut kemudian menggunakan kembali yang menggunakan ProductsComponent pada setiap acara yang dapat dilayari (produk dan produk /: id dll). Bisakah Anda menjelaskan atau mendemonstrasikan bagaimana ProductsComponent mungkin melakukan instantiasi ulang dalam kode di atas, dan bagaimana Anda akan mencegah instantiasi ulang?
ObjectiveTC
11

Jawaban rerezz cukup bagus tetapi memiliki satu kelemahan serius. Itu menyebabkan Userkomponen menjalankan kembali ngOnInitmetode.

Mungkin bermasalah ketika Anda melakukan beberapa hal yang berat di sana dan tidak ingin itu dijalankan kembali ketika Anda beralih dari rute non-parametrik ke yang parametrik. Meskipun kedua rute tersebut dimaksudkan untuk meniru parameter url opsional, tidak menjadi 2 rute terpisah.

Inilah yang saya sarankan untuk menyelesaikan masalah:

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

Kemudian Anda dapat memindahkan logika yang bertanggung jawab untuk menangani param ke UserWithParamkomponen dan meninggalkan logika dasar dalam Userkomponen. Apa pun yang Anda lakukan User::ngOnInittidak akan berjalan lagi ketika Anda menavigasi dari / pengguna ke / pengguna / 123 .

Jangan lupa untuk menempatkan <router-outlet></router-outlet>di User's Template.

matewka
sumber
Menghindari komponen yang dibuat ulang adalah hal yang baik jika kinerja sangat penting. Saya punya solusi lain yang juga menghindari komponen diciptakan kembali: stackoverflow.com/a/56391974/664533
Wayne Maurer
4

Jawaban yang disarankan di sini, termasuk jawaban yang diterima dari rerezz yang menyarankan menambahkan beberapa entri rute berfungsi dengan baik.

Namun komponen akan dibuat kembali ketika mengubah antara entri rute, yaitu antara entri rute dengan parameter dan entri tanpa parameter.

Jika Anda ingin menghindari ini, Anda dapat membuat pencocokan rute Anda sendiri yang akan cocok dengan kedua rute:

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

Kemudian gunakan pencocokan dalam konfigurasi rute Anda:

const routes: Routes = [
    {
        matcher: userPageMatcher,
        component: User,
    }
];
Wayne Maurer
sumber
@KevinBeal Saya telah menerapkan beberapa pencocokan yang bekerja dengan AOT. Apa kesalahan yang Anda dapatkan di sini?
Wayne Maurer
Ups. Itu sesuatu yang lain. Pencocokan saya bekerja dengan AOT.
Kevin Beal
ini sedikit rumit tetapi solusi terbaik untuk masalah ini
fedor.belov
4

Dengan angular4 kita hanya perlu mengatur rute bersama dalam hierarki

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

Ini bekerja untuk saya. Dengan cara ini router mengetahui apa rute berikutnya berdasarkan parameter id opsi.

Ravi Jadhav
sumber
1

Berlari ke contoh lain dari masalah ini, dan dalam mencari solusi untuk itu datang ke sini Masalah saya adalah saya mengerjakan anak-anak, dan malas memuat komponen juga untuk mengoptimalkan beberapa hal. Singkatnya jika Anda malas memuat modul induk. Hal utama adalah saya menggunakan '/: id' di rute, dan keluhan tentang '/' menjadi bagian dari itu. Bukan masalah sebenarnya di sini, tetapi itu berlaku.

Perutean aplikasi dari induk

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

Rute anak dimuat malas

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

Menghadapi masalah serupa dengan lazy loading, saya telah melakukan ini:

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

Dan kemudian di komponen:

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

Cara ini:

  • Rute tanpa /diarahkan ke rute dengan. Karena itu pathMatch: 'full', hanya rute lengkap khusus tersebut yang dialihkan.

  • Lalu, users/:idditerima. Jika rute yang sebenarnya adalah users/, idadalah "", jadi dalam ngOnInitdan bertindak sesuai; selain itu, idadalah id dan melanjutkan.

  • Komponen lainnya yang aktif selectedUseratau tidak terdefinisi (* ngIf dan hal-hal seperti itu).

Javier Sedano
sumber