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 { }