Angular 2
routing
Zoeken…
Basisroutering
Router maakt navigatie mogelijk van de ene weergave naar de andere op basis van gebruikersinteracties met de applicatie.
Hierna volgen de stappen voor het implementeren van basisroutering in hoek 2:
Fundamentele voorzorgsmaatregel : zorg ervoor dat u de tag hebt
<base href='/'>
als het eerste kind onder je hoofd-tag in je index.html-bestand. Deze tag geeft aan dat de map van uw app de hoofdmap van de app is. Angular 2 weet dan hoe je je links moet organiseren.
De eerste stap is om te controleren of u wijst op de juiste / laatste routeringsafhankelijkheden in package.json -
"dependencies": {
......
"@angular/router": "3.0.0-beta.1",
......
}
De tweede stap is om de route te definiëren volgens de klassedefinitie -
class Route {
path : string
pathMatch : 'full'|'prefix'
component : Type|string
.........
}
route/routes.ts
in een route/routes.ts
( route/routes.ts
) alle componenten die u moet configureren voor verschillende routeringspaden. Leeg pad betekent dat de weergave standaard wordt geladen. ":" in het pad geeft dynamische parameter aan die wordt doorgegeven aan de geladen component.
Routes worden beschikbaar gesteld voor toepassing via afhankelijkheidsinjectie. ProviderRouter-methode wordt aangeroepen met RouterConfig als parameter, zodat deze kan worden geïnjecteerd in de componenten voor het aanroepen van routeringsspecifieke taken.
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)];
De derde stap is het opstarten van de routeprovider.
In uw main.ts
(dit kan elke naam zijn. In principe moet uw hoofdbestand worden gedefinieerd in 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));
De vierde stap is het laden / weergeven van de routercomponenten op basis van het benaderde pad. richtlijn wordt gebruikt om hoekig te vertellen waar het onderdeel moet worden geladen. Om de ROUTER_DIRECTIVES te importeren.
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]
})
De vijfde stap is het koppelen van de andere routes. Standaard laadt RouterOutlet het onderdeel waarvoor een leeg pad is opgegeven in de RouterConfig. RouterLink-instructie wordt gebruikt met HTML-ankertag om de componenten te laden die aan routes zijn gekoppeld. RouterLink genereert het href-kenmerk dat wordt gebruikt om links te genereren. Voor 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 { }
Nu zijn we goed in routing naar statisch pad. RouterLink ondersteunt dynamisch pad, ook door extra parameters samen met het pad door te geven.
import {Component} uit '@ angular / core'; importeer {ROUTER_DIRECTIVES} van '@ 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 gebruikt een array waarbij het eerste element het pad voor routering is en de daaropvolgende elementen voor de dynamische routeringsparameters.
Kindroutes
Soms is het zinvol om weergaven of routes in elkaar te nestelen. Op het dashboard wilt u bijvoorbeeld verschillende subweergaven, vergelijkbaar met tabbladen maar geïmplementeerd via het routingsysteem, om de projecten, contacten, berichtenets van de gebruikers te tonen. Om dergelijke scenario's te ondersteunen, stelt de router ons in staat om kinderroutes te definiëren.
Eerst passen we onze RouterConfig
van boven aan en voegen de onderliggende routes toe:
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 }
];
Nu we onze onderliggende routes hebben gedefinieerd, moeten we ervoor zorgen dat die onderliggende routes kunnen worden weergegeven in onze DashboardComponent
, want daar hebben we de onderliggende routes aan toegevoegd. Eerder hebben we geleerd dat de componenten worden weergegeven in een tag <router-outlet></router-outlet>
. Op dezelfde manier verklaren we nog een RouterOutlet
in de 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 { }
Zoals u ziet, hebben we nog een RouterOutlet
toegevoegd waarin de onderliggende routes worden weergegeven. Meestal wordt de route met een leeg pad weergegeven, maar we stellen een omleiding naar de projects
, omdat we willen dat die direct wordt getoond wanneer de dashboard
wordt geladen. Dat gezegd hebbende, hebben we een lege route nodig, anders krijg je een foutmelding zoals deze:
Cannot match any routes: 'dashboard'
Dus door de lege route toe te voegen, wat een route met een leeg pad betekent, hebben we een toegangspunt voor de router gedefinieerd.
ResolveData
In dit voorbeeld wordt getoond hoe u gegevens kunt ophalen die u van een service hebt opgehaald voordat u de weergave van uw toepassing weergeeft.
Gebruikt angular / router 3.0.0-beta.2 op het moment van schrijven
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
Dit is een paginaonderdeel met een lijst van alle gebruikers. Het zal op dezelfde manier werken voor de component Gebruikersdetailpagina, data.users
vervangen door data.user
of welke sleutel dan ook gedefinieerd in app.routes.ts (zie hieronder)
... 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
Bundel desgewenst meerdere resolvers samen.
BELANGRIJK: Services die in de resolver worden gebruikt, moeten eerst worden geïmporteerd of u krijgt een 'Geen provider voor ..Resolver-fout'. Vergeet niet dat deze services wereldwijd beschikbaar zullen zijn en dat u ze niet meer bij providers
componenten hoeft aan te geven. Zorg ervoor dat u zich afmeldt voor elk abonnement om geheugenlekken te voorkomen
... import { UsersService } from './users.service'; import { UsersResolver } from './users.resolver'; export const ROUTE_RESOLVERS = [ ..., UsersService, UsersResolver ]
main.browser.ts
Resolvers moeten tijdens het bootstrappen worden geïnjecteerd.
... import {bootstrap} from '@angular/platform-browser-dynamic'; import { ROUTE_RESOLVERS } from './app.resolver'; bootstrap(<Type>App, [ ... ...ROUTE_RESOLVERS ]) .catch(err => console.error(err));
Routing met kinderen
In tegenstelling tot de originele documentatie, vond ik dit de manier om kinderroutes op de juiste manier in het bestand app.routing.ts of app.module.ts te nestelen (afhankelijk van uw voorkeur). Deze aanpak werkt bij het gebruik van WebPack of SystemJS.
Het onderstaande voorbeeld toont routes voor thuis, thuis / teller en thuis / teller / ophaalgegevens. De eerste en laatste routes zijn voorbeelden van omleidingen. Eindelijk aan het einde van het voorbeeld is een goede manier om de te importeren route in een afzonderlijk bestand te exporteren. Voor ex. app.module.ts
Om verder uit te leggen, vereist Angular dat u een pad zonder pad in de onderliggende array hebt dat de bovenliggende component bevat, om de bovenliggende route weer te geven. Het is een beetje verwarrend, maar als je denkt aan een lege URL voor een onderliggende route, zou deze in wezen dezelfde URL zijn als de bovenliggende route.
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 { }
Geweldig voorbeeld en beschrijving via Siraj