[[oktatas:web:angular|< Angular]] ====== Angular routing ====== * **Szerző:** Sallai András * Copyright (c) 2021, Sallai András * Szerkesztve: 2021, 2022, 2023, 2024, 2025 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC Attribution-Share Alike 4.0 International]] * Web: https://szit.hu ===== Útvonalak ===== Ha böngészőbe beírjuk: http://localhost:4200/egy ez egy URL. A port után részt nevezzük útvonalnak. Az útvonalak megadásával mondhatjuk meg, hogy milyen erőforrást szeretnénk elérni az adott szerveren. Esetünkben ez: * /egy Minden újabb útvonal egy újabb erőforrást jelölhet. Az Angularon belül, mi azt szeretnénk, ha egyik útvonalon egy komponens legyen elérhető, egy másik útvonalon egy másik. A példa kedvéért legyen 2 komponens: comp1 és comp2. Az comp1-t a /comp1 útvonalon, a comp2 komponenst a /comp2 útvonalon szeretnénk elérni. ^ Útvonal ^ Komponens ^ | /comp1 | comp1 | | /comp2 | comp2 | A célunk, hogy az app komponensen létrehozzunk egy navigációt. A navigációban alá szeretnénk betölteni, egyszer az egyik egyszer a másik komponenst. {{:oktatas:web:angular:componens_csere_01.png|}} ===== Útvonal létrehozása ===== Routingot több komponenssel használjuk. A routinggal mondjuk meg, melyik komponens jelenjen meg. A következőt szeretnénk: A böngészőben a tartománynév (domain név, ip cím, pl.: zold.lan) után megadok egy végpontot, akkor egy adott komponens betöltődjön. A következő példában comp1 helyett first nevű, a comp2 helyett second nevű komponenst használunk. | first | FirstComponent | | second | SecondComponent | A komponensek elkészítése: ng generate component first ng generate component second Az átirányítást az **app.routing.ts** állományban állítjuk, ami az **src/app/** könyvtárban található. Az állomány tartalma kezdetben: import { Routes } from '@angular/router'; export const routes: Routes = []; A Routes tömbben vegyünk fel két útvonalat: import { Routes } from '@angular/router'; import { FirstComponent } from './emp/first.component'; import { SecondComponent } from './role/second.component'; export const routes: Routes = [ { path: 'first', component: FirstComponent }, { path: 'second', component: SecondComponent } ]; Az útvonalakat JavaScript objektumként adjuk meg. Egy útvonalnak két kulcsot fogunk használni. Egy path és egy component kulcsot. A path tartalma az útvonal, a component tartalma a komponens teljes neve, ahogy a példában is látjuk. ===== Navigáció készítése ===== Fájl szinten és a dekorátorban is importálnunk kell a RouterLink és a RotuerOutlet modulokat: //... import { RouterLink, RouterOutlet } from '@angular/router'; //... imports: [CommonModule, RouterOutlet, RouterLink], //... Az app nevű komponensébe tesszük a "router-outlet" elemet, és előtte kialakítunk egy navigációt: Kattintásra a **router-outlet** elem helyén töltődik be, mindkét komponens lapja. Vegyük észre, hogy az "a" elem nem "href" attribútummal mutat az útvonalra. Ha href attribútumot használunk, az a weblap újratöltéséével jár. Helyette a **routerLink** attribútumot használjuk. ===== Végpontra irányítás ===== ==== HTML felületről ==== A routerLink számára megmondjuk, hogy "/task" útvonalat szeretném hívni. Erre már láttunk fentebb példát: Task Az útvonalak végén paramétert is átadhatunk: Paraméterátadással: Első ==== TypeScriptből ==== Ha valamilyen eseményre szeretnénk egy útvonalat meghívni, a Rotuer osztályt injektáljuk, például route néven, amin keresztül aktiválhatunk egy útvonalat. Importáljuk és injektáljuk a Router osztályt, majd a ''this.route.navigate(['/first']);'' utasítással hivatkozunk /first végpontra. import { Component, OnInit } from '@angular/core'; import {Router} from '@angular/router'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { title = 'app11'; constructor(private route:Router) { } ngOnInit():void { } goFirst():void { this.route.navigate(['/first']); } } ==== Paraméterátadás ==== Átadhatunk egy paramétert is, például azonosítót: onClickElement(task: Task): void { this.router.navigate(['task', task.id]); } Most vegyünk egy listát, ahol bármely elemre kattintva szeretném átadni a választott elemhez tartozó összes tulajdonságot. Az onClickElement függvény dolgozza fel a kattintást, a következő módon hívjuk: Így bármelyik listaelemre kattintva átadom a listaelemet a metódusnak. Az azonosítót a következő módon fogadhatjuk routing oldalon: { path: 'task/:id', component: TaskComponent }, Nézzünk egy lehetséges komplexebb példát: const routes: Routes = [ { path: 'first', component: FirstComponent }, { path: 'task/:id', component: TaskComponent }, { path: 'tasks', component: TasksComponent }, { path: 'home', component: HomeComponent }, { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '**', component: NopageComponent } ]; ===== 404 ===== Az Angular v2.2.2 vagy újabb verzió esetén wildcard karaktereket használhatunk, a meg nem határozott útvonalakhoz. | ** | FileNotFound | Ennek a bejegyzésnek mindig a végén kell szerepelni, mert ha erre az útvonalra rátalál a script, a többit már nem nézi meg. const routes: Routes = [ { path: 'first', component: FirstComponent }, { path: '**', component: Filenotfound }, ]; ==== Bővebb példa ==== const routes: Routes = [ { path: 'first', component: FirstComponent }, { path: 'home', component: HomeComponent }, { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '**', component: NopageComponent } ]; ===== Routing alkönyvtárakkal ===== //... const routes: Routes = [ { path: 'admin', component: AdminComponent, children: [ {path: 'login', component: LoginComponent}, {path: 'products', component: ProductsComponent, canActivate: [AuthGuard]} ] }, { path: '', component: WebsiteComponent, children: [ { path: 'buy', component: BuyComponent } ] } ]; //... A szülőkomponensekben el kell helyeznünk a **router-outlet** elemet: ===== Függelék ===== ==== Átirányítás és nopage ==== export const routes: Routes = [ { path: 'first', component: FirstComponent }, { path: 'task/:id', component: TaskComponent }, { path: 'tasks', component: TasksComponent }, { path: 'home', component: HomeComponent }, { path: '', redirectTo: 'home', pathMatch: 'full' }, { path: '**', component: NopageComponent } ]; ==== Feladatok teljes kód ==== export interface Task { id: number; name: string; } import { Task } from "./task"; export const TASKS: Task[] = [ { id: 1, name: "Angular tanulás" }, { id: 2, name: "React Native tanulás" }, { id: 3, name: "Adatabázis tanulás" }, ];

Feladatok

import { Component, OnInit } from '@angular/core'; import { TASKS } from '../tasks.storage'; import { Task } from '../task'; import { Router } from '@angular/router'; @Component({ selector: 'app-tasks', templateUrl: './tasks.component.html', styleUrls: ['./tasks.component.css'] }) export class TasksComponent implements OnInit { tasks!: Task[]; constructor(private router: Router) { } ngOnInit(): void { this.tasks = TASKS; } onClickElement(task: Task): void { this.router.navigate(['task', task.id]) } }

{{ tasks.id }} {{ tasks.name }}

Vissza
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { Task } from '../task'; import { TASKS } from '../tasks.storage'; @Component({ selector: 'app-task', templateUrl: './task.component.html', styleUrls: ['./task.component.css'] }) export class TaskComponent implements OnInit { tasks!: Task; constructor(private activatedRoute: ActivatedRoute) { } ngOnInit(): void { const id = Number(this.activatedRoute.snapshot.paramMap.get('id')); if (id) { this.tasks = TASKS.filter(task => task.id == id)[0]; } } }