Help us understand the problem. What is going on with this article?

Angularでスライドショー(1) 〜Routerでページの切り替え〜

More than 3 years have passed since last update.

はじめに

この記事では、Angularでスライドショーを作成する方法について説明します。
第1回目は、Router(ルーター)機能を使ったページの切り替えについてです。
(環境は、この記事の執筆時点の最新バージョンである Angular 4.3.4 です)

解説はいつものとおり「恋に落ちるコード.js」の絵子と樹里がお送りします。

人物紹介

瀬尾絵子:「恋に落ちるコード.js」の登場人物。JavaScript勉強中の女子高生。
篠宮樹里: 同じく「恋に落ちるコード.js」の登場人物。JavaScriptに詳しい女子高生。

目的

樹里「絵子、Angular CLIでスライドショーを作ってみよう」
絵子「相変わらず話が唐突だね。何でまた急に」
樹里「先日、同じくAngular CLIでRedmineのチケットの一覧を表示するWebアプリを作成したが」
絵子「うん。カンタンに出来るもんだなー、とビックリしちゃった」
樹里「Redmineで管理されているタスクは、結局のところRedmineにアクセスしないと確認できない。故に、常にRedmineを確認する習慣を付けないと見落としが発生する」
絵子「確かに。習慣を根付かせるまでは大変だよね」
樹里「そこで、APIからチケットの情報を取得してスライドショー形式で表示させれば、Redmineを開かずともタスクを確認することができる」
絵子「自然と目に入るもんね」
樹里「膨大なタスクの数にウンザリするも良し、いつまでも片付かない長寿タスクにウンザリするも良し」
絵子「何が良しなのかわからないけど、でも見える化って有効だよね」

ひな形を作成する

樹里「ではさっそく作ってみるが……絵子がちゃんと理解出来るよう、段階を追って作っていくぞ。今日の目標は、手動でのページ切り替えだ」
絵子「お気づかいありがとう」
樹里「さて、アプリ名だが……絵子、アプリ名はslideshowLeg-Fetishismのどっちがいい?」
絵子「ぜひslideshowでお願いします」
樹里「そうか。では」

ng new slideshow --routing

絵子「ひな形を自動で作ってくれるコマンドだね……でも樹里、最後の--routingって何?」
樹里「このオプションを追加すると、ルーティング用のモジュールも同時に作ってくれる。そして、そのモジュールこそが重要であり、今回の主役だ」
絵子「へー。……で、ルーティングって何?毛づくろいだっけ?」
樹里「そりゃグルーミングだ。全然合ってないぞ……ざっくり言うと、『こういうURLの時はこのコンテンツを表示させるよ』というルールを定義することだ。『/page1』というURLならpage1の内容を表示する、と言った具合に」
絵子「あ、それならわかるよ。それを早く言ってよ」
樹里「ただ、ルーティングはAngularでは基本中の基本機能なので、優良な解説記事はここQiitaを始めいくらでも存在する。詳しいことはそちらを参照するように。今回は、あくまで次回以降の記事の準備だと思ってほしい」
絵子「筋道立てて説明しないとね。ルートだけにね」

コンポーネントを追加する

樹里「では、ひな形が出来上がったところで、表示させるWebページのコンポーネントも追加しておこう。これもコマンドで簡単に出来る」

ng g component page1
ng g component page2
ng g component page3

樹里「gはgenerateの略で、生成するという意味だ。このコマンドを打つと、page1などのディレクトリが作られ、中に必要なファイルが生成される。とりあえず3ページ分作った」
絵子「おー、htmlとかcssとか色々できてる」
樹里「ファイルの生成は以上だ。次は、ひな形を修正していくぞ」

ルーティング用モジュールを修正する

樹里「それでは今回の主役、ルーティング用モジュールを修正しよう。app-routing.module.tsを開いて次のように書き換える」

app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
/* ↓(1) コンポーネントのインポート */
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';
/* ↑ */

const routes: Routes = [
/*
  {
    path: '',
    children: []
  }
*/
/* ↓(2) ルーティングの設定 */
  {
    path: 'page1',
    component: Page1Component,
  },
  {
    path: 'page2',
    component: Page2Component,
  },
  {
    path: 'page3',
    component: Page3Component
  }
/* ↑ */
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

(1)コンポーネントのインポート

樹里「さっき作った3つのコンポーネントを読み込んでいるだけだ」
絵子「あなたの出番ですよー、って教えてあげているわけだね」

(2)ルーティングの設定

樹里「ここでルーティングを設定してるわけだが」
絵子「思ってたよりシンプルだね。しかも、何を言わんとしてるのか何となくわかる。つまり、『page1』というURLにアクセスしたら『Page1Component』を表示させなさい、っていう風に指定してるんだよね?」
樹里「その通り。ただ、従来のWebページとは違い、URLの遷移によってページ全体が書き換わるわけではない。書き換わるのは、あくまでページの一部だけだ」
絵子「ふーん」

メインコンポーネントを修正する

樹里「では、メインのコンポーネントであるapp.component.tsを見てみよう」

app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
}

絵子「……特に変わったところはなさそうだけど」
樹里「そう。このファイルは、今回は修正するところはない。その代わり、HTMLのテンプレートを次のように書き換える」

app.component.html
<p>
  <a routerLink="/page1">page1</a>
  <a routerLink="/page2">page2</a>
  <a routerLink="/page3">page3</a>
</p>
<p>この下の部分が切り替わるよ!</p>
<router-outlet></router-outlet>

樹里「一番下の<router-outlet></router-outlet>の部分が、ルーティングによって書き換えられる部分だ。逆に言うと、それ以外の部分は一切変化しない」
絵子「なるほど」
樹里「で、リンク先に遷移するためには見慣れた<a>要素を使うのだが、hrefならぬrouterLinkディレクティブというものを用いる」
絵子「なるほど」

メインモジュールを確認する

樹里「では最後に、メインのモジュールであるapp.module.tsを見てみよう

app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { Page1Component } from './page1/page1.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';

@NgModule({
  declarations: [
    AppComponent,
    Page1Component,
    Page2Component,
    Page3Component
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

絵子「あ、Page1Componentとかがいつの間にか追加されてる」
樹里「そう、ng gコマンドでコンポーネントを追加すると、app.module.tsにも自動で追加してくれるのだ」
絵子「気が効くよねー」
樹里「なので、このモジュールも特に書き換えるところはない」

動作確認

樹里「では、さっそく動かしてみよう」

ng s

絵子「コマンド短っ!」
樹里「sserveの略だ。これだけでサーバーが起動する。では。さっそく http://localhost:4200/ にアクセスしよう」
絵子「リンクが3つ並んでるね。クリックすると……おー、『page1 works!』だって」
樹里「それはpage1.component.htmlの内容だな。他のリンクをクリックすると、当然他のページが表示される」
絵子「うんうん、ちゃんと切り替わってる」
樹里「アドレスバーを見ると、 http://localhost:4200/page1 と言うように、URLも切り替わってるのがわかるだろう。アドレスバーに直接URLを入力しても同じ結果になるぞ」
絵子「本当だ」
樹里「このように、『URLに応じて表示するコンポーネントを切り替える』というのは、Angularを使う上で非常に重要な機能なので、ぜひ覚えてほしい」
絵子「はーい」

次回予告

次回は、タイマーによるページの自動遷移について解説します。

8amjp
福井市に住むSE・プログラマ。Kindleストアで技術系異世界ファンタジー小説「Redmineで始める異世界人心掌握術」販売中。JavaScript学園コメディ「恋に落ちるコード.js」電子書籍化準備中。
https://8am.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away