با مطالعه دو بخش ۱ و ۲ از فصل ۷ اطلاعات نسبتا مناسبی در ارتباط با مسیردهی (Routing) در انگولار ۴ کسب کردید. حال در ادامهی این دو بخش، مبحث مسیردهی را در سطح پیشرفتهتر بررسی میکنیم و در نهایت در فصل ۷-۴ با ارائهی مباحث امنیتی مسیرها این فصل را به اتمام میرسانیم. با ما همراه باشید.
همانطور که در مثال گذشته ملاحظه کردید توانستیم با استفاده از پارامترها پویایی و داینامیک بودن اطلاعات یک صفحه را ایجاد کرده و با تبادل اطلاعات ببین کامپوننت و آدرس درخواستی، مشخصات دقیق هر سرور یا کاربری را نمایش دهیم. حال در این قسمت میخواهیم در ادامهی مثال قبل، تعیین سطح دسترسی برای ویرایش یک سرور و یا کاربر را به صورت خیلی ساده و مقدماتی خدمت شما عزیزان آموزش دهیم. توجه داشته باشید که تعیین سطح دسترسی یک فصل جداگانه را به خود اختصاص میدهد اما در این بخش میخواهیم شما را با مفاهیم مقدماتی آن آشنا کنیم. برای انجام اینکار ابتدا فایل server.component.html را باز کرده و یک دکمه برای ویرایش سرور همانند زیر ایجاد میکنیم:
<h5>{{ server.name }}</h5> <p>وضعیت سرور: {{ server.status }}</p> <button class="btn btn-primary" (click)="onEditServer()">ویرایش سرور</button>
سپس درنظر داریم که وقتی کاربر روی دکمهی «ویرایش سرور» کلیک کرد به صفحهی ویرایش سرور منتقل شود. در این حالت باید فایل server.component.html را باز کرده و درون متد onEditServer از متد navigate به صورت زیر استفاده کنیم:
import {Component, OnDestroy, OnInit} from '@angular/core'; import {ServersService} from '../servers.service'; import {ActivatedRoute, Params, Router} from "@angular/router"; import {Subscription} from "rxjs"; @Component({ selector: 'app-server', templateUrl: './server.component.html', styleUrls: ['./server.component.css'] }) export class ServerComponent implements OnInit, OnDestroy { server: { id: number, name: string, status: string }; paramsSubscribtion: Subscription; constructor(private serversService: ServersService, private route: ActivatedRoute, private router: Router) { } ngOnInit() { const id = +this.route.snapshot.params['id']; this.server = this.serversService.getServer(id); this.paramsSubscribtion = this.route.params.subscribe( (params: Params) => { this.server = this.serversService.getServer(+params['id']) } ); } ngOnDestroy(){ this.paramsSubscribtion.unsubscribe(); } onEditServer(){ this.router.navigate(['edit'], {relativeTo: this.route}) } }
در این مرحله میخواهیم تعیین کنیم که چه کاربری اجازهی بروزرسانی و ویرایش یک سرور را بر عهده داشته باشد. بنابراین وارد فایل servers.component.html شده و در نهایت تغییرات زیر را برای ویژگی queryParams انجام میدهیم:
[queryParams]="{allowEdit: server.id == 3 ? '1': '0'}"
سپس فایل edit-server.component.ts را باز کرده و در قسمت مربوط به هوک ngOnInit متد queryParams را به صورت زیر تغییر میدهید:
import {Component, OnInit} from '@angular/core'; import {ServersService} from '../servers.service'; import {ActivatedRoute, Params} from "@angular/router"; @Component({ selector: 'app-edit-server', templateUrl: './edit-server.component.html', styleUrls: ['./edit-server.component.css'] }) export class EditServerComponent implements OnInit { server: { id: number, name: string, status: string }; serverName = ''; serverStatus = ''; allowEdit = false; constructor(private serversService: ServersService, private route: ActivatedRoute) { } ngOnInit() { this.route.queryParams.subscribe( (queryParams: Params) =>{ this.allowEdit = queryParams['allowEdit'] == 1 ? true : false; } ); this.route.fragment.subscribe(); this.server = this.serversService.getServer(1); this.serverName = this.server.name; this.serverStatus = this.server.status; } onUpdateServer() { this.serversService.updateServer(this.server.id, {name: this.serverName, status: this.serverStatus}); } }
در نهایت فایل edit-server.component.html را نیز به صورت زیر تغییر میدهیم:
<h4 *ngIf="allowEdit == false">شما اجازه دسترسی به این بخش را ندارید</h4> <div *ngIf="allowEdit == true"> <div class="form-group"> <label for="name">نام سرور</label> <input type="text" id="name" class="form-control" [(ngModel)]="serverName"> </div> <div class="form-group"> <label for="status">وضعیت سرور</label> <select id="status" class="form-control" [(ngModel)]="serverStatus"> <option value="online">روشن</option> <option value="offline">خاموش</option> </select> </div> <button class="btn btn-primary" (click)="onUpdateServer()">بروزرسانی سرور </button> </div>
بسیار عالی کار به اتمام رسید. حال اگر روی دکمهی ویرایش سرور کلیک کنید طبیعتا به صفحهای مشابه تصویر زیر روبهرو خواهید شد:
اما یک مشکلی در این مثال وجود دارد وقتی شما روی گزینه سوم یعنی «سرور توسعه روکسو» کلیک میکنید علیرغم اینکه مقدار id سرور برای ۳ است ولی باز هم سطح دسترسی را برای شما ایجاد نمیکند. برای حل این مشکل باید از یک ویژگی به نام queryParamsHandling استفاده کرد که باید به فایل server.component.ts و در متد navigate اضافه کنیم. این ویژگی باعث میشود که اطلاعات پارامترهای موجود در آدرس پس از کلیک کردن روی دکمهی «ویرایش سرور» از بین نرود. برای ویژگی queryParamsHandling دو مقدار میتوان لحاظ کرد:
به عنوان مثال فرض کنید آدرس اصلی صفحه سرور ما به صورت زیر است:
http://localhost:4200/servers/3?allowEdit=1#loading
حال اگر از merge استفاده کنیم آدرس پس از کلیک روی دکمه به صورت زیر خواهد شد:
http://localhost:4200/servers//3/edit?allowEdit=1
و اگر از preserve استفاده کنیم این آدرس به صورت زیر تغییر میکند:
http://localhost:4200/servers//3/edit?allowEdit=1&page=3
بنابراین در فایل server.component.ts داریم:
this.router.navigate(['edit'], {relativeTo: this.route, queryParamsHandling: 'preserve'})
بسیار عالی حال اگر روی ویرایش سرور کلیک کنید برای سرور سوم صفحه و فرم ویرایش نمایش داده خواهد شد. البته این نرمافزار هنوز نیاز به بهینهسازی بیشتری دارد چون اطلاعات موجود در فرم با اطلاعات سرور شماره ۳ یکسان نیست. در آینده به اصلاح این بخش میپردازیم.
اگر کاربر در صفحه شما یک آدرس مشابه http://localhost:4200/something را وارد کند، در صفحه کنسول خطا ایجاد شده و به او نمایش داده میشود. اما برای طراحی و بهینهسازی حرفهای وبسایت باید کاربر را به سمتی هدایت کنیم که اگر صفحهای را اشتباه وارد کرد به مسیر مشخصی انتقال پیدا کند. برای انجام اینکار ابتدا یک کامپوننت جدید به نام page-not-found با دستور زیر ایجاد میکنیم:
ng g c page-not-found
سپس در فایل page-not-found.component.html پیام زیر را قرار میدهیم:
<h3>صفحه موردنظر یافت نشد!</h3>
در نهایت به فایل app.module.ts مراجعه کرده و مسیردهی موجود در ویژگی appRoutes را به صورت زیر ویرایش خواهیم کرد:
const appRoutes: Routes = [ {path: '', component: HomeComponent}, { path: 'users', component: UsersComponent, children: [ {path: ':id/:name', component: UserComponent}, ] }, { path: 'servers', component: ServersComponent, children: [ {path: ':id', component: ServerComponent}, {path: ':id/edit', component: EditServerComponent} ] }, {path: 'not-found', component: PageNotFoundComponent}, {path: '**', redirectTo: '/not-found'} ];
همانطور که ملاحظه میکنید ابتدا یک مسیر به نام http://localhost:4200/not-found ایجاد کردیم که از کامپوننت page-not-found پیروی میکند. سپس در خط آخر این ویژگی یک مسیر با ساختار ** ایجاد کرده و آن را به مسیر not-found ریدایرکت کردهایم. علامت دو ستاره ** به معنی تمام مسیرهایی که تعریف نشده است.
نکته بسیار مهم: حتما و حتما باید علامت ** و مسیری که شامل این علامت میشود در آخرین خط متغییر appRoutes تعریف شود زیرا مسیرها در انگولار از بالا به پایین خوانده میشوند و اگر ما این مسیر را در بالاترین نقطه تعریف کنیم تمام صفحات به صورت پیشفرض not-found خواهند بود.
بسیار عالی به شما عزیزان تبریک میگوییم در این بخش توانستید تواناییهایی جدید را در زمینه کار با مسیردهیها کسب کنید. اما یکی از مباحثی که همواره برای ما حائز اهمیت است، مبحث امنیت میباشد. در بخش بعدی ابزارهای جدیدی را تولید و مورد استفاده قرار میدهیم تا امنیت مسیردهیها در بالاترین سطح ممکن قرار گیرد. با ما همراه باشید.
توجه: دوستان عزیز آموزش ویدیویی انگولار ۵ از مقدماتی تا پیشرفته به زبان فارسی را میتوانید با کلیک روی اینجا یاد بگیرید. (این دوره در حال برگزاری است)
فصل ۱
فصل ۲
فصل ۳: خطایابی (Debugging) در انگولار ۴
فصل ۴
فصل ۵
فصل ۶
فصل ۷
فصل ۸: معرفی Observable یا مشاهده کنندهها در انگولار ۴
فصل ۹
در این قسمت، به پرسشهای تخصصی شما دربارهی محتوای مقاله پاسخ داده نمیشود. سوالات خود را اینجا بپرسید.