Angular 2
Le routage
Recherche…
Routage de base
Le routeur permet la navigation d'une vue à l'autre en fonction des interactions de l'utilisateur avec l'application.
Voici les étapes de la mise en œuvre du routage de base dans Angular 2 -
Précaution élémentaire : Assurez-vous d'avoir l'étiquette
<base href='/'>
comme premier enfant sous votre balise head dans votre fichier index.html. Cette balise indique que votre dossier d'application est la racine de l'application. Angular 2 sait alors organiser vos liens.
La première étape consiste à vérifier si vous pointez sur les dépendances de routage correctes / les plus récentes dans package.json -
"dependencies": {
......
"@angular/router": "3.0.0-beta.1",
......
}
La deuxième étape consiste à définir l'itinéraire selon sa définition de classe -
class Route {
path : string
pathMatch : 'full'|'prefix'
component : Type|string
.........
}
Dans un fichier de routes ( route/routes.ts
), importez tous les composants que vous devez configurer pour différents chemins de routage. Chemin vide signifie que la vue est chargée par défaut. ":" dans le chemin indique un paramètre dynamique transmis au composant chargé.
Les routes sont mises à la disposition des applications via l'injection de dépendances. La méthode ProviderRouter est appelée avec le paramètre RouterConfig pour pouvoir être injectée dans les composants pour appeler des tâches spécifiques au routage.
import { provideRouter, RouterConfig } from '@angular/router';
import { BarDetailComponent } from '../components/bar-detail.component';
import { DashboardComponent } from '../components/dashboard.component';
import { LoginComponent } from '../components/login.component';
import { SignupComponent } from '../components/signup.component';
export const appRoutes: RouterConfig = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
{ path: 'dashboard', component: DashboardComponent },
{ path: 'bars/:id', component: BarDetailComponent },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignupComponent }
];
export const APP_ROUTER_PROVIDER = [provideRouter(appRoutes)];
La troisième étape consiste à amorcer le fournisseur de route.
Dans votre main.ts
(il peut s'agir de n'importe quel nom. En gros, votre fichier principal devrait être défini dans systemjs.config)
import { bootstrap } from '@angular/platform-browser-dynamic';
import { AppComponent } from './components/app.component';
import { APP_ROUTER_PROVIDER } from "./routes/routes";
bootstrap(AppComponent, [ APP_ROUTER_PROVIDER ]).catch(err => console.error(err));
La quatrième étape consiste à charger / afficher les composants du routeur en fonction du chemin d'accès accédé. directive est utilisée pour indiquer angulaire où charger le composant. Pour utiliser import le ROUTER_DIRECTIVES.
import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
selector: 'demo-app',
template: `
....................................
<div>
<router-outlet></router-outlet>
</div>
....................................
`,
// Add our router directives we will be using
directives: [ROUTER_DIRECTIVES]
})
La cinquième étape consiste à relier les autres itinéraires. Par défaut, RouterOutlet charge le composant pour lequel le chemin vide est spécifié dans RouterConfig. La directive RouterLink est utilisée avec la balise d'ancrage HTML pour charger les composants associés aux itinéraires. RouterLink génère l'attribut href qui est utilisé pour générer des liens. Pour ex:
import { Component } from '@angular/core';
import { ROUTER_DIRECTIVES } from '@angular/router';
@Component({
selector: 'demo-app',
template: `
<a [routerLink]="['/login']">Login</a>
<a [routerLink]="['/signup']">Signup</a>
<a [routerLink]="['/dashboard']">Dashboard</a>
<div>
<router-outlet></router-outlet>
</div>
`,
// Add our router directives we will be using
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }
Maintenant, nous sommes bons avec le routage vers le chemin statique. RouterLink prend également en charge le chemin dynamique en transmettant des paramètres supplémentaires avec le chemin.
import {Composant} de '@ angulaire / core'; import {ROUTER_DIRECTIVES} depuis '@ angular / router';
@Component({
selector: 'demo-app',
template: `
<ul>
<li *ngFor="let bar of bars | async">
<a [routerLink]="['/bars', bar.id]">
{{bar.name}}
</a>
</li>
</ul>
<div>
<router-outlet></router-outlet>
</div>
`,
// Add our router directives we will be using
directives: [ROUTER_DIRECTIVES]
})
export class AppComponent { }
RouterLink prend un tableau où le premier élément est le chemin de routage et les éléments suivants sont destinés aux paramètres de routage dynamique.
Itinéraires enfant
Parfois, il est logique d'imbriquer les vues ou les itinéraires les uns dans les autres. Par exemple, sur le tableau de bord, vous voulez plusieurs sous-vues, similaires aux onglets mais implémentées via le système de routage, pour afficher les projets, les contacts, les messages des utilisateurs. Pour prendre en charge de tels scénarios, le routeur nous permet de définir des itinéraires enfants.
Nous ajustons d'abord notre RouterConfig
ci-dessus et ajoutons les routes enfants:
import { ProjectsComponent } from '../components/projects.component';
import { MessagesComponent} from '../components/messages.component';
export const appRoutes: RouterConfig = [
{ path: '', pathMatch: 'full', redirectTo: 'login' },
{ path: 'dashboard', component: DashboardComponent,
children: [
{ path: '', redirectTo: 'projects', pathMatch: 'full' },
{ path: 'projects', component: 'ProjectsComponent' },
{ path: 'messages', component: 'MessagesComponent' }
] },
{ path: 'bars/:id', component: BarDetailComponent },
{ path: 'login', component: LoginComponent },
{ path: 'signup', component: SignupComponent }
];
Maintenant que nos routes enfants sont définies, nous devons nous assurer que ces routes enfants peuvent être affichées dans notre DashboardComponent
, car nous avons ajouté les enfants. Auparavant, nous avons appris que les composants sont affichés dans une <router-outlet></router-outlet>
. De même, nous déclarons un autre RouterOutlet
dans DashboardComponent
:
import { Component } from '@angular/core';
@Component({
selector: 'dashboard',
template: `
<a [routerLink]="['projects']">Projects</a>
<a [routerLink]="['messages']">Messages</a>
<div>
<router-outlet></router-outlet>
</div>
`
})
export class DashboardComponent { }
Comme vous pouvez le voir, nous avons ajouté un autre RouterOutlet
dans lequel les routes enfants seront affichées. Habituellement, la route avec un chemin vide sera affichée, cependant, nous configurons une redirection vers la route du projects
, car nous voulons que celle-ci soit affichée immédiatement lorsque la route du dashboard
est chargée. Cela étant dit, nous avons besoin d'un itinéraire vide, sinon vous obtiendrez une erreur comme celle-ci:
Cannot match any routes: 'dashboard'
Donc, en ajoutant la route vide , c'est-à-dire une route avec un chemin vide, nous avons défini un point d'entrée pour le routeur.
ResolveData
Cet exemple vous montre comment résoudre les données extraites d'un service avant d'afficher la vue de votre application.
Utilise angular / router 3.0.0-beta.2 au moment de l'écriture
users.service.ts
... import { Http, Response } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { User } from './user.ts'; @Injectable() export class UsersService { constructor(public http:Http) {} /** * Returns all users * @returns {Observable<User[]>} */ index():Observable<User[]> { return this.http.get('http://mywebsite.com/api/v1/users') .map((res:Response) => res.json()); } /** * Returns a user by ID * @param id * @returns {Observable<User>} */ get(id:number|string):Observable<User> { return this.http.get('http://mywebsite.com/api/v1/users/' + id) .map((res:Response) => res.json()); } }
users.resolver.ts
... import { UsersService } from './users.service.ts'; import { Observable } from 'rxjs/Rx'; import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from "@angular/router"; @Injectable() export class UsersResolver implements Resolve<User[] | User> { // Inject UsersService into the resolver constructor(private service:UsersService) {} resolve(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<User[] | User> { // If userId param exists in current URL, return a single user, else return all users // Uses brackets notation to access `id` to suppress editor warning, may use dot notation if you create an interface extending ActivatedRoute with an optional id? attribute if (route.params['id']) return this.service.get(route.params['id']); return this.service.index(); } }
users.component.ts
Ceci est un composant de page avec une liste de tous les utilisateurs. Il fonctionnera de la même manière pour le composant de la page de détail de l'utilisateur, remplacez data.users
par data.user
ou la clé définie dans app.routes.ts (voir ci-dessous).
... import { ActivatedRoute} from "@angular/router"; @Component(...) export class UsersComponent { users:User[]; constructor(route: ActivatedRoute) { route.data.subscribe(data => { // data['Match key defined in RouterConfig, see below'] this.users = data.users; }); } /** * It is not required to unsubscribe from the resolver as Angular's HTTP * automatically completes the subscription when data is received from the server */ }
app.routes.ts
... import { UsersResolver } from './resolvers/users.resolver'; export const routes:RouterConfig = <RouterConfig>[ ... { path: 'user/:id', component: UserComponent, resolve: { // hence data.user in UserComponent user: UsersResolver } }, { path: 'users', component: UsersComponent, resolve: { // hence data.users in UsersComponent, note the pluralisation users: UsersResolver } }, ... ] ...
app.resolver.ts
Combinez éventuellement plusieurs résolveurs ensemble.
IMPORTANT: Les services utilisés dans le résolveur doivent être importés en premier ou vous obtiendrez un "Aucun fournisseur pour l'erreur ..Resolver". N'oubliez pas que ces services seront disponibles dans le monde entier et que vous n'aurez plus à les déclarer dans les providers
de composants. Veillez à vous désabonner de tout abonnement pour éviter toute fuite de mémoire
... import { UsersService } from './users.service'; import { UsersResolver } from './users.resolver'; export const ROUTE_RESOLVERS = [ ..., UsersService, UsersResolver ]
main.browser.ts
Les résolveurs doivent être injectés lors du bootstrap.
... import {bootstrap} from '@angular/platform-browser-dynamic'; import { ROUTE_RESOLVERS } from './app.resolver'; bootstrap(<Type>App, [ ... ...ROUTE_RESOLVERS ]) .catch(err => console.error(err));
Routage avec des enfants
Contrairement à la documentation d'origine, j'ai trouvé que c'était le moyen d'imbriquer correctement les routes enfants dans le fichier app.routing.ts ou app.module.ts (selon vos préférences). Cette approche fonctionne lorsque vous utilisez WebPack ou SystemJS.
L'exemple ci-dessous montre les routes pour les données home, home / counter et home / counter / fetch. Les premier et dernier itinéraires sont des exemples de redirections. Enfin, à la fin de l'exemple, vous pouvez exporter la route à importer dans un fichier distinct. Pour ex. app.module.ts
Pour mieux expliquer, Angular exige que vous ayez un itinéraire sans chemin dans le tableau d'enfants qui inclut le composant parent, pour représenter la route parente. C'est un peu déroutant, mais si vous pensez à une URL vide pour une route enfant, elle correspondrait essentiellement à la même URL que la route parente.
import { NgModule } from "@angular/core";
import { RouterModule, Routes } from "@angular/router";
import { HomeComponent } from "./components/home/home.component";
import { FetchDataComponent } from "./components/fetchdata/fetchdata.component";
import { CounterComponent } from "./components/counter/counter.component";
const appRoutes: Routes = [
{
path: "",
redirectTo: "home",
pathMatch: "full"
},
{
path: "home",
children: [
{
path: "",
component: HomeComponent
},
{
path: "counter",
children: [
{
path: "",
component: CounterComponent
},
{
path: "fetch-data",
component: FetchDataComponent
}
]
}
]
},
{
path: "**",
redirectTo: "home"
}
];
@NgModule({
imports: [
RouterModule.forRoot(appRoutes)
],
exports: [
RouterModule
]
})
export class AppRoutingModule { }
Excellent exemple et description via Siraj