Açısal 2 isteğe bağlı rota parametresi


180

Açısal 2 yolunda isteğe bağlı bir rota parametresine sahip olmak mümkün müdür? RouteConfig Açısal 1.x sözdizimi denedim ama aşağıdaki hata aldı:

"ORİJİNAL İSTİSNA: Yol" / kullanıcı /: id? ", Bir rota yapılandırmasında izin verilmeyen"? "İçeriyor."

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

Yanıtlar:


298

Parametre ile veya parametre olmadan birden fazla rota tanımlayabilirsiniz:

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

ve bileşeninizde isteğe bağlı parametreyi kullanın:

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

    if (paramId) {
        ...
    }
}

Ayrıca ilgili github sorununa da bakın: https://github.com/angular/angular/issues/3525


11
Yanılıyorsam beni düzeltin, ancak bu çözüm yalnızca dizideki rotaların sırası tersine çevrildiğinde, yani parametreli rota diğerinden önce gerçekleştiğinde benim için çalıştı. Bunu yapana kadar, yönlendirici rotayı sadece parametre olmadan eşleştirdi.
Aviad P.

10
bu çözüm hala geçerli mi? "Kullanıcı" dan "UserNew" 'e geçiş' Kullanıcı 'bileşeni yeniden somutlaşacak fark ettim
teleaziz

19
eski ama bu yaklaşımla ilgili önemli bir sorun, her bir yolun benzersiz bir yol olarak ele alınması ve bileşenin yeniden kullanılmasını imkansız hale getirmesidir.
Acı

4
@Teleaziz tarafından belirtildiği gibi, parametrenin eklenmesi bileşeni yeniden oluşturur. Bundan kaçınmak için Martin Cremer'ın cevabı; boş bir parametre değeri olan bir 'redirectTo' kökü eklemek benim için çok işe yaradı: stackoverflow.com/a/49159166/1364650 - ama bu oldukça hacky, bence isteğe bağlı rota parametrelerini düzgün bir şekilde desteklemeliler.
Vincent Sels

2
Bileşene neden RouteParamsaktarmadığınızı merak edenler için şunu kontrol edin: stackoverflow.com/a/36792261/806202 . Çözüm ActivatedRoute:route.snapshot.params['routeParam']
Arsen Khachaturyan

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

Bu şekilde, parametre eklendiğinde bileşen yeniden oluşturulmaz.


6
Bu cevap en iyisidir. Aynı bileşeni yeniden oluşturmaz ve birden çok bileşen gerektirmez.
Rex

4
En iyi cevap, ama pathMatch: 'full'yönlendirmeye ekledim , aksi takdirde yollar users/adminda benim durumumda yönlendiriliyor
Valeriy Katkov

4
Bu yanıt, yalnızca tarayıcılarınızda göründüğü gibi URL'lerinizde eğik çizgi varsa sorun gidermez. Örneğin, 'tanımsız bir kimliği' temsil eden bir değeri düşünün /users/allya /users/homeda 'tümünü' veya 'ev'i' olarak okuyun ve idsihirli değerinizle eşleşiyorsa yoksayın. Sonra yukarıdaki ilk satır redirectTo: 'users/home'ya da ne karar verirseniz verin. Bana göre bir eğik çizgi gerçekten yanlış bir şey olarak göze çarpıyor.
Simon_Weaver

@Simon_Weaver katılıyorum. Bu sorunu olmayan bir eşleştirici kullanarak başka bir çözüm buldum: stackoverflow.com/a/56391974/664533
Wayne Maurer

1
basit bir büyü ama kırılmaz: D En iyi çözüm!
Verri

45

Bilgiler isteğe bağlı olduğunda bir sorgu parametresi kullanılması önerilir.

Rota Parametreleri veya Sorgu Parametreleri?

Zor ve hızlı bir kural yoktur. Genel olarak,

Aşağıdaki durumlarda rota parametresini tercih edin

  • değer gereklidir.
  • değer bir rota yolunu diğerinden ayırmak için gereklidir.

Aşağıdaki durumlarda bir sorgu parametresi tercih edin

  • değer isteğe bağlıdır.
  • değer karmaşık ve / veya çoklu-değişkendir.

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

Parametreyi rota yolundan çıkarmanız yeterlidir.

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

6
İsteğe bağlı rota parametrelerini değiştirmek bileşenleri yeniden oluşturur, ancak queryParams'ı değiştirmek olmaz. Ayrıca, rota navigasyonundan önce bazı verileri çözerseniz, isteğe bağlı rota parametrelerini her değiştirdiğinizde veri istenir.
Rakhat

1
Bilginize, bu çapa bağlantısı artık çalışmıyor. Yeni bağlantı Güzergah Parametreleri
spottedmahn

20

Açısal 4 - İsteğe bağlı parametrenin sırasını ele almak için çözüm:

BUNU YAP:

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

productsVe products/:idyollarının aynı şekilde adlandırıldığını unutmayın . Açısal 4, productsparametresiz rotalar için doğru bir şekilde takip eder ve eğer bir parametre varsa takip eder products/:id.

Bununla birlikte, sigara parametre yoldan yolunu productsgerekir değil , bir eğik çizgi, başka türlü açısal yanlış bir parametre-yolu olarak algılar. Benim durumumda, ürünler için sondaki eğik çizgi vardı ve işe yaramadı.

BUNU YAPMAYIN:

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

Her ikisi de ProductsComponent'e gidiyorsa, oradaki isteğe bağlı parametre ile nasıl başa çıkıyorsunuz?
Arwin

1
: İd1,: id2, etc parametrelerine ve ProductsComponent'te istenen url'ye şu şekilde erişebilirsiniz: this.route.url.first () .mergeMap ((url) => {// console.log ('1: url değişikliği algılandı '+ url); this.route.params.do ((params) => {// console.log (' 2: url + params değişikliği tespit edildi '+ params ["id1"] +' '+ params döndür ["id2"]); this.id1 = params ["id1"]; this.id2 = params ["id2"];})})
ObjectiveTC

2
dataAynı bileşene bile her rota için farklı olabilen bileşene de geçebileceğinizi unutmayın . Örnek {path: 'products', component: ProductsComponent, data: { showAllProducts: true} },kullanılabilir ve sonra kontrol edin showAllProducts. Biraz daha hoş bir null için kontrol, ama daha basit durumlarda ya da muhtemelen iyi.
Simon_Weaver

1
Ne yazık ki, bu çözüm Angular ürününün ürünler ve ürünler /: id arasında bileşeni yeniden kullanmasını engelleyecektir. Bileşen yeniden somutlaştırılacaktır.
Kodiak

@Kodiak - Bunun doğru olduğuna inanmıyorum. Anladığım kadarıyla app.module.ts dosyasında ProductsComponent bileşeninin bir kez başlatıldığı ve açısal motorun daha sonra bu gezilebilir her olayda (ürünler ve ürünler /: id vb.) Başlatılan ProductsComponent bileşenini yeniden kullandığıdır. ProductsComponent bileşeninin yukarıdaki kodda nasıl yeniden somutlaştığını ve yeniden somutlaşmayı nasıl önleyeceğinizi açıklayabilir veya gösterebilir misiniz?
ObjectiveTC

11

rerezz'un cevabı oldukça güzel ama ciddi bir kusuru var. UserBileşenin ngOnInityöntemi yeniden çalıştırmasına neden olur .

Orada bazı ağır şeyler yaptığınızda sorunlu olabilir ve parametrik olmayan rotadan parametrik olana geçtiğinizde yeniden çalıştırılmasını istemezsiniz. Bu iki yolun isteğe bağlı bir url parametresini taklit etmesine rağmen, 2 ayrı yol haline gelmez.

Sorunu çözmek için önerdiğim şey:

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

Ardından, parametrenin işlenmesinden sorumlu mantığı taşıyabilir UserWithParamve temel mantığı bileşende bırakabilirsiniz User. İçinde yaparsanız yapın User::ngOnInitsiz gittiğinizde tekrar çalıştırmak olmayacak / kullanıcı için / kullanıcı / 123 .

Koymak unutma <router-outlet></router-outlet>içinde Userbireyin şablona.


Performans kritikse yeniden oluşturulmakta olan bileşenden kaçınmak iyi bir şeydir. Bileşenin yeniden oluşturulmasını önleyen başka bir çözüm daha var: stackoverflow.com/a/56391974/664533
Wayne Maurer

4

Dahil Burada önerilen cevaplar, kabul edilen cevabını gelen rerezz birden rota girişleri çalışma cezası eklemenizi öneririz.

Ancak bileşen, rota girişleri arasında, yani parametreli rota girişi ile parametresiz giriş arasında değişiklik yaparken yeniden oluşturulur.

Bundan kaçınmak istiyorsanız, her iki güzergahla da eşleşen kendi güzergah eşleştiricinizi oluşturabilirsiniz:

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

Ardından rota yapılandırmanızdaki eşleştiriciyi kullanın:

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

@KevinBeal AOT ile çalışan birkaç eşleştirici uyguladım. Buraya gelen hata nedir?
Wayne Maurer

Hata. Başka bir şeydi. Eşleştiricim AOT ile çalışıyor.
Kevin Beal

Bu biraz zor ama bu soruna en iyi çözüm
fedor.belov

4

Angular4 ile rotaları hiyerarşide birlikte organize etmemiz gerekiyor

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

Bu benim için çalışıyor. Bu şekilde yönlendirici, seçenek kimliği parametrelerine dayalı olarak bir sonraki yolun ne olduğunu bilir.


1

Bu sorunun başka bir örneğiyle karşılaştım ve bunun çözümü için buraya geldi. Benim sorunum, şeyleri biraz optimize etmek için çocukları ve bileşenlerin tembel yüklemesini yapıyordum. Kısacası ana modülü yüklerken tembelseniz. Önemli olan rotada '/: id' kullanmamdı ve '/' bunun bir parçası olmakla ilgili şikayetler. Burada tam bir sorun değil, ama geçerli.

Üst öğeden uygulama yönlendirmesi

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

Çocuk yolları tembel yüklendi

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


0

Tembel yükleme ile benzer bir sorunla karşılaştım bunu yaptım:

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

Ve sonra bileşende:

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

Bu yoldan:

  • Olmadan rota /ile rotaya yönlendirilir. Bu nedenle pathMatch: 'full', yalnızca bu tür tam yol yeniden yönlendirilir.

  • Sonra users/:idalınır. Gerçek rota ise users/, idolduğu "", yani içinde kontrol ngOnInitve buna göre hareket; başka, idid ve devam.

  • Bileşenlerin geri kalanı etkisizdir selectedUserveya tanımlanmamıştır (* ngIf ve bunun gibi şeyler).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.