Routes parameters

כשיש לנו רשימה של מוצרים/משתמשים וכו' ואנחנו רוצים להכנס לתוך ערך אחד, אנחנו צריכים פרמטר שיגיד לנו באיזה מוצר אנחנו נמצאים. הכתובת נבנית באופן אוטומטי ונראית משהו כמו: url/courses/course/103

במודול שבו נמצאים ה-routes אנחנו מוסיפים את הנתיב למוצר שלנו.

app.module.ts

{ path: 'courses/course/:id', component: CourseComponent },

כדי לקבל את ה-id אנחנו יכולים להשתמש ב-activated route.

course.component.ts

constructor(private activatedRoute: ActivatedRoute) {}

ngOnInit(): void {
    this.courseId = this.activatedRoute.snapshot.paramMap.get('id');
}

עכשיו אפשר לפנות ל-service ולמצוא שם את המוצר שאותו אנחנו מחפשים.

course.component.ts

constructor(private activatedRoute: ActivatedRoute) {}

ngOnInit(): void {
    this.courseId = this.activatedRoute.snapshot.paramMap.get('id');
    this.course = this.courseService.find(x => x.id == this.courseId);
}

בעמוד הקורסים נחבר את הקישורים לכפתור שמוביל לעמוד המוצר.

courses.component.html

<button routerLink="/courses/course/{{course.id}}" type="button" 
    class="btn btn-sm btn-outline-secondary">
    View Details
</button>

שימוש ב-Observable לקבל את הפרמטר מהכתובת

משתנה ה-snapshot מחזיק את הערך הראשוני של הפרמטר שמופיע בכתובת, אבל לא את השינויים שמתבצעים בפרמטר.

אם בעמוד הקורס נרצה לשלוח לקישור של קורס אחר, ה-snapshot לא יראה את השינוי.

course.component.html

<a [routerLink]="['/courses/course/', 101]">Go to first course</a>

בלחיצה, הכתובת תשתנה אבל לא התוכן של העמוד.

אנחנו מקבלים את המידע של snapshot בפונקציית OnInit שרצה פעם אחת, ואם נשנה את הקישור, הפונקציה הזאת לא נקראת שוב.

שימוש ב-snapshot טוב כשאנחנו יודעים שאין קריאה נוספת לאותה קומפוננטה מתוך הקומפוננטה שבה אנחנו נמצאים. אם יש קריאה כשאת נשתמש ב-observable.

course.component.ts

ngOnInit(): void {
    this.routeParamObs = this.activatedRoute.paramMap.subscribe((param) => {
      this.courseId = param.get('id');
      this.course = this.courseService.find(x => x.id == this.courseId);
    })
}
  
ngOnDestroy(){
    this.routeParamObs.unsubscribe();
}

Query parameters

עם Query parameters אנחנו יכולים להעביר מידע נוסף דרך שורת הכתובת של העמוד. למשל את שם המוצר, שיטת מיון של טבלה וכו'. אלו פרמטרים אופציונלים לעמוד.

נניח שאנחנו רוצים לעשות את הכותרת של העמוד אפשרית לעריכה על ידי המשתמש.

course.component.html

<div>
    <h1>Course name: {{ course.name}}</h1>
</div>

<button>Edit</button>

נגדיר משתנה editMode שהערך ההתחלתי שלו יהיה false. כשהוא false נציג את הכותרת כ-h1, כלומר לא ניתנת לעריכה.

course.component.ts

editMode: boolean = false;

נוסיף שדה input שיקבל את התוכן שאותו רוצים להכניס, והוא יופיע רק אם הערך של editMode יהיה true.

הכפתור ישלח אותנו לאותו הנתיב בו אנחנו נמצאים, אבל יוסיף את הערך של הפרמטר edit כך שנוכל לקרוא אותו מהדף.

course.component.html

<div>
    <h1 *ngIf="!editMode">Course name: {{ course.name}}</h1>
    <input type="text" [(ngModel)]="course.name" *ngIf="editMode">
</div>

<button [routerLink]="['/courses/course/', course.id]" 
    [queryParams]="{edit: true}">Edit</button>

אפשר לשלוח את הפרמטר גם דרך פונקציה ולא ישירות דרך הקישור.

course.component.html

<button (click)="appendQueryParam()">Edit</button>

ולהוסיף את הפרמטר דרך הפונקציה.

course.component.ts

constructor(private router: Router) {}

appendQueryParam(){
    this.router.navigate(['/courses/course/', this.courseId], {queryParams: {edit: true}})
}

קבלת ערכי query parameters

את הערכים של הפרמטרים אנחנו מקבלים דרך הנתיב של העמוד.

course.component.ts

ngOnInit(): void {
    this.activatedRoute.queryParamMap.subscribe((param) => {
      this.editMode = Boolean(param.get('edit'));
    }); 
}

קישורים פנימיים

קישור פנימי הוא קישור לחלק בתוך העמוד שבו אנחנו נמצאים.

לחלק בעמוד שאליו אנחנו רוצים לגשת ניתן id ובקישורים נשלח ל-id הזה עם משתנה fragment.

html file

<div>
    <app-home id="home"></app-home>
    <app-about id="about"></app-about>
</div>

<a routerLink="" fragment="home"></a>
<a routerLink="" fragment="about"></a>

בקובץ ה-class נקבל את הנתיב הנוכחי ונגדיר פונקציה שמגוללת את העמוד למקום הנכון.

ts file

constructor(private activatedRoute: ActivatedRoute, private router: Router) {}

ngOnInit(): void {
    this.activatedRoute.fragment.subscribe((value) => {
      this.jumpTo(value);
    });
}

jumpTo(section: any){
    document.getElementById(section)?.scrollIntoView({behavior: 'smooth'});
}