Angular 2
ルーティング
サーチ…
基本的なルーティング
ルーターは、アプリケーションとのユーザーのやりとりに基づいて、あるビューから別のビューへのナビゲーションを可能にします。
次に、基本的なルーティングを角度2で実装する手順を示します。
基本的な予防策 :タグがあることを確認してください
<base href='/'>
あなたのindex.htmlファイルのheadタグの下の最初の子として。このタグは、アプリケーションフォルダがアプリケーションルートであることを示します。 Angular 2はあなたのリンクを整理することを知っています。
最初のステップは、package.jsonの正しい/最新のルーティング依存関係を指しているかどうかを確認することです。
"dependencies": {
......
"@angular/router": "3.0.0-beta.1",
......
}
2番目のステップは、クラス定義に従ってルートを定義することです。
class Route {
path : string
pathMatch : 'full'|'prefix'
component : Type|string
.........
}
ルートファイル( route/routes.ts )で、異なるルーティングパス用に構成する必要があるすべてのコンポーネントをインポートします。空のパスは、デフォルトでビューが読み込まれることを意味します。パス内の「:」は、ロードされたコンポーネントに渡される動的パラメータを示します。
依存関係の注入を介して、アプリケーションにルートが提供されます。 ProviderRouterメソッドは、パラメータとしてRouterConfigを使用して呼び出され、ルーティング固有のタスクを呼び出すためにコンポーネントに注入できるようにします。
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)];
第3のステップは、ルートプロバイダをブートストラップすることです。
あなたのmain.ts (それは任意の名前でもmain.tsませんが、基本的には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));
第4のステップは、アクセスされたパスに基づいてルータコンポーネントをロード/表示することである。ディレクティブは、コンポーネントをロードする場所を指定するために使用されます。 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]
})
第5ステップは、他のルートをリンクすることです。デフォルトでは、RouterOutletは空のパスが指定されているコンポーネントをRouterConfigにロードします。 RouterLinkディレクティブはhtmlアンカータグとともに使用され、ルートに接続されたコンポーネントをロードします。 RouterLinkは、リンクを生成するために使用されるhref属性を生成します。例:
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 { }
さて、私たちは静的なパスにルーティングすることで良いです。 RouterLinkは、パスとともに余分なパラメータを渡すことによっても動的パスをサポートします。
'@ angle / core'から{Component}をインポートします。 '@ angular / router'から{ROUTER_DIRECTIVES}をインポートします。
@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は配列を取ります。最初の要素はルーティング用のパスで、後続の要素は動的なルーティングパラメータ用です。
子ルート
ビューやルートを互いに入れ子にすることは意味があります。たとえば、ダッシュボードでは、タブに似ていますが、ルーティングシステム経由で実装されたいくつかのサブビューが必要で、ユーザーのプロジェクト、連絡先、メッセージを表示します。このようなシナリオをサポートするために、ルーターは子ルートを定義することができます。
最初にRouterConfigを上から調整し、子ルートを追加します:
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 }
];
子ルートが定義されたので、子ルートをDashboardComponent内に表示できるようにする必要があります.DashboardComponentは子ルートを追加した場所です。以前は、コンポーネントが<router-outlet></router-outlet>タグに表示されていることがわかりました。同様にDashboardComponent別のRouterOutletを宣言し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 { }
ご覧のとおり、子ルートが表示される別のRouterOutletが追加されました。通常はパスが空のルートが表示されますが、 projectsルートへのリダイレクトはdashboardルートがロードされるとすぐに表示されるように設定されています。つまり、空のルートが必要です。そうしないと、次のようなエラーが表示されます。
Cannot match any routes: 'dashboard'
空のルートを追加することで、空のパスを持つルートを意味し、ルーターのエントリポイントを定義しました。
ResolveData
この例では、アプリケーションのビューをレンダリングする前に、サービスからフェッチされたデータを解決する方法を示します。
執筆時点で角度/ルータ3.0.0-beta.2を使用
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
これはすべてのユーザーのリストを持つページコンポーネントです。 User detail pageコンポーネントでも同様にdata.usersし、 data.usersをdata.userまたはdata.usersで定義されているキーに置き換えます (下記参照)
...
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
複数のリゾルバを一緒にバンドルすることもできます。
重要: リゾルバで使用されるサービスは、最初にインポートする必要があります。または「..Resolverエラーのプロバイダがありません」というメッセージが表示されます。これらのサービスは世界中で提供される予定であるため、コンポーネントのprovidersで宣言する必要はありません。メモリリークを防ぐため、定期購読を解除するようにしてください
...
import { UsersService } from './users.service';
import { UsersResolver } from './users.resolver';
export const ROUTE_RESOLVERS = [
...,
UsersService,
UsersResolver
]
main.browser.ts
ブートストラップ時にリゾルバーを注入する必要があります。
...
import {bootstrap} from '@angular/platform-browser-dynamic';
import { ROUTE_RESOLVERS } from './app.resolver';
bootstrap(<Type>App, [
...
...ROUTE_RESOLVERS
])
.catch(err => console.error(err));
子供とのルーティング
オリジナルのドキュメントとは対照的に、これはapp.routing.tsファイルまたはapp.module.tsファイル内の子ルートを適切にネストする方法であることがわかりました(好みに応じて)。このアプローチは、WebPackまたはSystemJSを使用する場合に機能します。
次の例は、ホーム、ホーム/カウンタ、およびホーム/カウンタ/フェッチデータのルートを示しています。最初と最後のルートはリダイレクトの例です。最後に、例の最後に、別のファイルにインポートするルートをエクスポートする適切な方法があります。例えば、 app.module.ts
さらに説明すると、Angularでは、親ルートを表すために、親コンポーネントを含む子配列内にパスレスルートがあることが必要です。ちょっと混乱しますが、子ルートの空白のURLについて考えると、親ルートと同じURLになります。
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 { }