Sierですが何か?

仕事、趣味などで興味を持った技術など(ブログタイトル迷走中)

【AngularJS】angular-ui-routerを使ってメニューから表示する内容を切り替える

f:id:shinji-fsi-5761:20161008022107j:plain

10cmです。こんにちは。今回は、AngularJSの"angular-ui-router"(以下、ui-router)を用いて、メニューバーから表示する内容を切り替える処理を記載していきます。

はじめに、完成イメージです。 "コンテンツA"と"コンテンツB"のリンクがあり、それぞれ専用の画面を表示します。今回の例では、"コンテンツA"は赤い四角を、"コンテンツB"は緑の四角を表示します。

コンテンツA
f:id:shinji-fsi-5761:20161009194843p:plain

コンテンツB
f:id:shinji-fsi-5761:20161009194906p:plain

以下に、今回のディレクトリ構成を示します。

ディレクトリ構成
----------------------

カレントディレクトリ
 ├ index.html
 ├ app.js
 ├ controller
 │  └ header.js
 ├ view	
 │  ├ main.html
 │  ├ header.html
 │  ├ contentA.html
 │  └ contentB.html
 └ node_modules
    ├ angular
    └ angular-ui-router 

メニューの作成 (header.html, header.js)

まず、メニューの作成を行います。以下にソースコードを示します。

header.html
----------------------

<header>
  <ul ng-repeat="l in HeaderCtrl.list">
    <a ui-sref="main.{{l.link}}"><li>{{l.name}}</li></a>
  </ul>
</header>
header.js
----------------------

var HeaderCtrl = function($scope) {
  this.list = [
    {
        'link': 'contentA',
        'name': 'コンテンツA'
    },
    {
        'link': 'contentB',
        'name': 'コンテンツB'
    }
  ];
};
app.controller('HeaderController', HeaderCtrl);

"a"タグの中に書かれている"ui-sref"ですが、詳しくは後ろで解説します。ここでは"href"のように、飛ぶ先を示しているのだと認識してください。つまり、『"main.{{l.link}}という場所が設定されていて、リンクを押すとそこに飛ぶんだな。』ということです。

l.linkは、"header.js"に書いてある"list"の中身を、1つずつ取り出しています。この例では、"コンテンツA"と画面上に表示されていて、そのリンク先は"main.contentA"となります。

コンテンツの作成 (contentA.html, contentB.html)

次に、メニューを押下した時に表示するコンテンツを作成します。といっても、ここでは四角を表示するHTMLファイルを書くだけです。

一応ソースコードは以下のようになります。

contentA.html
----------------------

<div style="height:100px; width:100px; background-color:#ff0000">
  <p style="color: #ffffff">ContentA</p>
</div>
contentB.html
----------------------

<div style="height:100px; width:100px; background-color:#00ff00">
  <p style="color: #000000">ContentB</p>
</div>

メニューとコンテンツの紐付け (index.html, main.html, app.js)

ここでメニューと作ったコンテンツの紐付けを行います。その前に、表示切り替えのイメージの説明をしたいと思います。

f:id:shinji-fsi-5761:20161009195555p:plain

メニューが選択されたとき、設定されていた"ui-sref"の値を表示しろと"app.js"に通知します。"app.js"は、その値に紐づくHTMLファイルを"main.html"に表示させます。

そのため、メニューに設定している"ui-sref"の値と、"app.js"に記載する値を一致させる必要があります。それでは、実際のソースコードを見てみましょう。

index.html
----------------------

<body ng-app="MyApp">
  <!-- UI-Routerの設定 -->
  <ui-view name="header"></ui-view>
  <ui-view name="main"></ui-view>
</body>
main.html
----------------------

<ui-view name="content"></ui-view>
app.js
----------------------

var app = angular.module('MyApp', ['ui.router']);

app.config(function($stateProvider, $urlRouterProvider){
  $stateProvider.state('main',{
    'url': '/',
    'views': {
        // Header
        'header': {
            'templateUrl': './view/header.html',
            'controller': 'HeaderController',
            'controllerAs': 'HeaderCtrl'
        },
        'main': {
            'templateUrl': './view/main.html',
        }
        //ContentA
	}}).state('main.contentA', {
            'url': 'contentA',
            'views': {
                'content': {
                    'templateUrl': './view/contentA.html',
                }
        //ContentB
        }}).state('main.contentB', {
            'url': 'contentB',
            'views': {
                'content': {
                'templateUrl': './view/contentB.html',
        }
  }});
  $urlRouterProvider.otherwise('/');
});

"index.html"には、メニューと、 コンテンツを表示するための"ui-view"があります。メニューには"header.html"を、コンテンツには"main.html"をapp.jsで指定しています。

"main.html"には、"content"を表示するための"ui-view"が設定されています。ここに対して、"contentA"か"contentB"のHTMLファイルを表示します。

では、どうやって表示するものを決定するかですが、"app.js"の"state"に書かれています。"contentA"の場合は"main.contentA"が設定されています。これは、"header.html"のui-sref"と同じ値が設定されています。

つまり、コンテンツAを押下したとき、"ui-sref"に設定されている"state"と同じものを表示させます。では何を表示させるのか。"content"の"templateUrl"に設定されているHTMLを表示させます。今回の例では、"./view/contentA.html"が表示されます。

まとめ

"ui-view"を階層化することで、表示するものを切り替えることができるようになりました。"ui-view"や"ui-sref"、"app.js"に記述する"state"など色々出てきましたが、それぞれの関連性について理解できたでしょうか?

ここで言うのもなんですが、自分はまだ理解できていないと思います(汗)。

参考

UI-Router API Reference