พารามิเตอร์เส้นทางเสริม Angular 2


180

เป็นไปได้หรือไม่ที่จะมีพารามิเตอร์เส้นทางทางเลือกในเส้นทาง Angular 2 ฉันลองใช้ไวยากรณ์ Angular 1.x ใน RouteConfig แต่ได้รับข้อผิดพลาดด้านล่าง:

"ข้อยกเว้นเดิม: เส้นทาง" / ผู้ใช้ /: id? "มี"? "ซึ่งไม่ได้รับอนุญาตในการกำหนดค่าเส้นทาง

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

คำตอบ:


298

คุณสามารถกำหนดหลายเส้นทางโดยมีและไม่มีพารามิเตอร์:

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

และจัดการพารามิเตอร์ทางเลือกในองค์ประกอบของคุณ:

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

    if (paramId) {
        ...
    }
}

ดูเพิ่มเติมที่ปัญหา GitHub ที่เกี่ยวข้อง: https://github.com/angular/angular/issues/3525


11
แก้ไขให้ฉันถ้าฉันผิด แต่วิธีนี้ใช้ได้ผลกับฉันเฉพาะเมื่อลำดับเส้นทางในอาเรย์ถูกย้อนกลับนั่นคือเส้นทางที่มีพารามิเตอร์เกิดขึ้นก่อนหน้านี้ จนกว่าฉันจะทำเช่นนั้นเราเตอร์จะจับคู่เส้นทางที่ไม่มีพารามิเตอร์เท่านั้น
Aviad P.

10
วิธีนี้ยังใช้ไม่ได้? ฉันสังเกตว่าการเปลี่ยนจาก "ผู้ใช้" เป็น "ผู้ใช้ใหม่" จะยกตัวอย่างองค์ประกอบ 'ผู้ใช้' อีกครั้ง
teleaziz

19
เก่า แต่ปัญหาสำคัญของวิธีนี้คือแต่ละเส้นทางจะถือว่าเป็นเส้นทางที่ไม่ซ้ำกันและทำให้องค์ประกอบกลับมาใช้ซ้ำไม่ได้
ความเจ็บปวด

4
ดังที่บันทึกไว้โดย @teleaziz การผนวกพารามิเตอร์จะทำให้องค์ประกอบแสดงผลอีกครั้ง เพื่อหลีกเลี่ยงปัญหานี้คำตอบของ Martin Cremer; การเพิ่มรูท 'redirectTo' ด้วยค่าพารามิเตอร์ว่างทำงานได้ดีสำหรับฉัน: stackoverflow.com/a/49159166/1364650 - แต่มันค่อนข้างแฮ็คฉันคิดว่าพวกเขาควรสนับสนุนพารามิเตอร์ตัวเลือกอย่างถูกต้อง
Vincent Sels

2
สำหรับผู้ที่กำลังสงสัยว่าทำไมRouteParamsไม่นำเข้าตรวจสอบส่วนนี้: stackoverflow.com/a/36792261/806202 ทางออกคือการใช้ActivatedRoute:route.snapshot.params['routeParam']
Arsen Khachaturyan

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

วิธีนี้คอมโพเนนต์จะไม่ถูกเรนเดอร์อีกครั้งเมื่อมีการเพิ่มพารามิเตอร์


6
คำตอบนี้ดีที่สุด ไม่แสดงองค์ประกอบเดียวกันซ้ำและไม่ต้องใช้หลายองค์ประกอบ
เร็กซ์

4
คำตอบที่ดีที่สุด แต่ฉันเพิ่มpathMatch: 'full'การเปลี่ยนเส้นทางมิฉะนั้นเส้นทางเช่นusers/adminถูกเปลี่ยนเส้นทางในกรณีของฉัน
Valeriy Katkov

4
คำตอบนี้ดีที่สุดถ้าคุณตกลงกับการต่อท้ายทับ URL ของคุณเมื่อดูในเบราว์เซอร์ ลองพิจารณาค่าที่แสดงถึง 'รหัสที่ไม่ได้กำหนด' ตัวอย่างเช่น/users/allหรือ/users/homeอ่าน 'ทั้งหมด' หรือ 'บ้าน' เป็นidและเพียงแค่ละเว้นถ้ามันตรงกับค่าเวทย์มนตร์ของคุณ จากนั้นบรรทัดแรกด้านบนจะกลายเป็นredirectTo: 'users/home'หรืออะไรก็ตามที่คุณตัดสินใจ สำหรับฉันแล้วตัวต่อท้ายที่โดดเด่นเป็นสิ่งที่ผิดปกติ
Simon_Weaver

@Simon_Weaver ฉันเห็นด้วย ฉันพบวิธีแก้ไขปัญหาอื่นโดยใช้เครื่องจับคู่ที่ไม่มีปัญหานี้: stackoverflow.com/a/56391974/664533
Wayne Maurer

1
มันเป็นคาถาที่เรียบง่าย แต่ค่อนข้างจะแตกได้: D ทางออกที่ดีที่สุด!
Verri

45

ขอแนะนำให้ใช้พารามิเตอร์ข้อความค้นหาเมื่อมีข้อมูลหรือไม่ก็ได้

พารามิเตอร์เส้นทางหรือพารามิเตอร์การสืบค้น

ไม่มีกฎที่ยากและรวดเร็ว โดยทั่วไปแล้ว

ชอบพารามิเตอร์เส้นทางเมื่อ

  • จำเป็นต้องมีค่า
  • ค่าจำเป็นต้องแยกแยะเส้นทางเส้นทางหนึ่งจากเส้นทางอื่น

ต้องการพารามิเตอร์เคียวรีเมื่อ

  • ค่าเป็นทางเลือก
  • ค่ามีความซับซ้อนและ / หรือหลายตัวแปร

จากhttps://angular.io/guide/router#optional-route-parameters

คุณเพียงแค่ต้องนำพารามิเตอร์ออกจากเส้นทางเส้นทาง

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

6
การเปลี่ยนเส้นทางพารามิเตอร์เสริมเลือกส่วนประกอบแสดงผล แต่การเปลี่ยน queryParams ไม่ได้ นอกจากนี้หากคุณแก้ไขข้อมูลบางส่วนก่อนการนำทางเราจะขอข้อมูลทุกครั้งเมื่อคุณเปลี่ยนพารามิเตอร์เส้นทางเพิ่มเติม
Rakhat

1
FYI ลิงก์ตัวยึดนั้นใช้งานไม่ได้อีกต่อไป ลิงค์ใหม่ดูเหมือนจะเป็นพารามิเตอร์เส้นทาง: จำเป็นหรือไม่ก็ได้?
spottedmahn

20

Angular 4 - โซลูชันเพื่อจัดการการเรียงลำดับของพารามิเตอร์ทางเลือก:

ทำเช่นนี้:

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

โปรดทราบว่าproductsและproducts/:idเส้นทางมีชื่อเหมือนกันทุกประการ Angular 4 จะติดตามproductsเส้นทางที่ไม่มีพารามิเตอร์อย่างถูกต้องและหากพารามิเตอร์นั้นจะติดตามproducts/:idเส้นทางที่มีพารามิเตอร์ไม่มีและถ้าพารามิเตอร์มันจะเป็นไปตาม

อย่างไรก็ตามเส้นทางสำหรับเส้นทางที่ไม่ใช่พารามิเตอร์productsจะต้องไม่เครื่องหมายทับท้ายมิฉะนั้นเชิงมุมจะถือว่าเป็นเส้นทางพารามิเตอร์อย่างไม่ถูกต้อง ดังนั้นในกรณีของฉันฉันมีเครื่องหมายทับสำหรับผลิตภัณฑ์และมันไม่ทำงาน

อย่าทำอย่างนี้:

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

หากทั้งสองกำลังไปที่ ProductsComponent คุณจะจัดการกับพารามิเตอร์ทางเลือกที่นั่นได้อย่างไร
Arwin

1
คุณสามารถเข้าถึงพารามิเตอร์: id1,: id2 และอื่น ๆ รวมถึง URL ที่ร้องขอใน ProductsComponent ดังนี้: this.route.url.first () .mergeMap ((url) => {// console.log ('1: ตรวจพบการเปลี่ยนแปลง url '+ url); ส่งคืน this.route.params.do ((params) => {// console.log (' 2: url + params ตรวจพบการเปลี่ยนแปลง '+ params ["id1"] +' '+ params ["id2"]); this.id1 = params ["id1"]; this.id2 = params ["id2"];})})
ObjectiveTC

2
จำไว้ว่าคุณสามารถส่งdataต่อไปยังองค์ประกอบได้เช่นกันซึ่งอาจแตกต่างกันไปในแต่ละเส้นทางแม้กระทั่งไปยังองค์ประกอบเดียวกัน ตัวอย่างเช่นสามารถนำมาใช้และจากนั้นคุณตรวจสอบ{path: 'products', component: ProductsComponent, data: { showAllProducts: true} }, showAllProductsnicer เล็กน้อยแล้วตรวจสอบ null แต่สำหรับกรณีที่ง่ายกว่าอาจเป็นเรื่องปกติ
Simon_Weaver

1
น่าเสียดายที่โซลูชันนี้จะป้องกัน Angular ไม่ให้นำส่วนประกอบระหว่างผลิตภัณฑ์และผลิตภัณฑ์ /: id กลับมาใช้ซ้ำ ส่วนประกอบจะได้รับการติดตั้งใหม่
Kodiak

@ Kodiak - ฉันไม่เชื่อว่าถูกต้อง ความเข้าใจของฉันคือใน app.module.ts, ProductsComponent จะถูกสร้างขึ้นหนึ่งครั้งและจากนั้นเครื่องยนต์เชิงมุมก็จะใช้ ProductsComponent ที่สร้างอินสแตนซ์ใหม่ให้กับเหตุการณ์การนำทางแต่ละครั้ง (ผลิตภัณฑ์และผลิตภัณฑ์ /: id ฯลฯ ) คุณสามารถอธิบายหรือแสดงให้เห็นว่า ProductsComponent อาจจะสร้างอินสแตนซ์ใหม่ในรหัสด้านบนได้อย่างไรและคุณจะป้องกันการสร้างอินสแตนซ์ใหม่ได้อย่างไร
ObjectiveTC

11

คำตอบของ rerezz นั้นค่อนข้างดี แต่มันมีข้อบกพร่องอย่างหนึ่ง มันทำให้Userองค์ประกอบที่จะเรียกใช้ngOnInitวิธีการใหม่

มันอาจเป็นปัญหาเมื่อคุณทำของหนัก ๆ ที่นั่นและไม่ต้องการให้มันถูกเรียกใช้ซ้ำเมื่อคุณเปลี่ยนจากเส้นทางที่ไม่ใช่พารามิเตอร์ไปเป็นพารามิเตอร์หนึ่ง แม้ว่าเส้นทางทั้งสองนั้นมีจุดประสงค์เพื่อเลียนแบบพารามิเตอร์ url ที่เป็นทางเลือก แต่จะไม่แยกเป็น 2 เส้นทาง

นี่คือสิ่งที่ฉันแนะนำเพื่อแก้ไขปัญหา:

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

จากนั้นคุณสามารถย้ายตรรกะที่รับผิดชอบในการจัดการพารามิเตอร์ไปยังUserWithParamคอมโพเนนต์และออกจากฐานตรรกะในUserส่วนประกอบ สิ่งที่คุณทำUser::ngOnInitจะไม่ทำงานอีกเมื่อคุณนำทางจาก/ ผู้ใช้ไปยัง/ ผู้ใช้ / 123 /

อย่าลืมที่จะใส่ <router-outlet></router-outlet>ในUserแม่แบบของ


การหลีกเลี่ยงองค์ประกอบที่ถูกสร้างใหม่เป็นสิ่งที่ดีถ้าประสิทธิภาพมีความสำคัญ ฉันมีวิธีแก้ไขปัญหาอื่นซึ่งช่วยหลีกเลี่ยงส่วนประกอบที่สร้างใหม่: stackoverflow.com/a/56391974/664533
Wayne Maurer

4

คำตอบที่แนะนำที่นี่รวมถึงคำตอบที่ยอมรับจากrerezzซึ่งแนะนำให้เพิ่มหลายรายการเส้นทางทำงานได้ดี

อย่างไรก็ตามส่วนประกอบจะถูกสร้างขึ้นใหม่เมื่อเปลี่ยนระหว่างรายการเส้นทางเช่นระหว่างรายการเส้นทางที่มีพารามิเตอร์และรายการที่ไม่มีพารามิเตอร์

หากคุณต้องการหลีกเลี่ยงปัญหานี้คุณสามารถสร้างตัวจับคู่เส้นทางของคุณเองซึ่งจะจับคู่ทั้งสองเส้นทาง:

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

จากนั้นใช้ตัวจับคู่ในการกำหนดเส้นทางของคุณ:

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

@KevinBeal ฉันได้ทำการแมตช์ค่อนข้างน้อยซึ่งทำงานกับ AOT อะไรคือข้อผิดพลาดที่คุณได้รับที่นี่
Wayne Maurer

อุ่ย มันเป็นอย่างอื่น Matcher ของฉันทำงานกับ AOT
Kevin Beal

นี่เป็นเรื่องยุ่งยากเล็กน้อย แต่ทางออกที่ดีที่สุดสำหรับปัญหานี้
fedor.belov

4

ด้วย angular4 เราเพียงแค่ต้องจัดเส้นทางด้วยกันในลำดับชั้น

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

มันใช้งานได้สำหรับฉัน วิธีนี้เราเตอร์จะรู้ว่าเส้นทางต่อไปคืออะไรขึ้นอยู่กับพารามิเตอร์รหัสตัวเลือก


1

พบกับปัญหานี้อีกครั้งและในการค้นหาวิธีแก้ไขปัญหาก็มาที่นี่ ปัญหาของฉันคือฉันกำลังทำกับเด็ก ๆ และการโหลดองค์ประกอบที่ขี้เกียจเช่นกันเพื่อเพิ่มประสิทธิภาพของสิ่งต่าง ๆ เล็กน้อย ในระยะสั้นถ้าคุณขี้เกียจโหลดโมดูลหลัก สิ่งสำคัญคือฉันใช้ '/: id' ในเส้นทางและเป็นข้อร้องเรียนเกี่ยวกับ '/' เป็นส่วนหนึ่งของมัน ไม่ใช่ปัญหาที่แน่นอนที่นี่ แต่ใช้

การกำหนดเส้นทางแอปจากพาเรนต์

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

เส้นทางเด็กขี้เกียจโหลด

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

0

ฉันไม่สามารถแสดงความคิดเห็น แต่อ้างอิงถึง: พารามิเตอร์เส้นทางทางเลือก 2 Angular

การอัปเดตสำหรับ Angular 6:

import {map} from "rxjs/operators"

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

  if (paramId) {
    ...
  }
}

ดูhttps://angular.io/api/router/ActivatedRouteสำหรับข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดเส้นทาง Angular6


0

เผชิญกับปัญหาที่คล้ายกันกับการโหลดที่ขี้เกียจฉันได้ทำสิ่งนี้แล้ว:

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

และจากนั้นในองค์ประกอบ:

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

ทางนี้:

  • เส้นทางที่ไม่มีการ/เปลี่ยนเส้นทางไปยังเส้นทางด้วย เนื่องจากpathMatch: 'full'เส้นทางเต็มเท่านั้นจึงถูกเปลี่ยนเส้นทาง

  • จากนั้นusers/:idได้รับ หากเส้นทางที่เกิดขึ้นจริงusers/, idคือ""เพื่อให้ตรวจสอบในngOnInitและดำเนินการตาม; อื่นidเป็นรหัสและดำเนินการต่อ

  • ส่วนที่เหลือของส่วนที่ทำหน้าที่selectedUserเป็นหรือไม่ได้กำหนด (* ngIf และสิ่งต่าง ๆ เช่นนั้น)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.