YEOMANでAngularJSプロジェクトにControllerを追加する
メモ。
YEOMANでジェネレータgenerate-angular
をインストールしている場合、
以下のコマンドでControllerの作成も自動でやってくれます。
# 生成したいプロジェクトディレクトリ上で実行 $ yo angular:controller MyNewController # 生成 create app/scripts/controllers/mynewcontroller.js create test/spec/controllers/mynewcontroller.js
ただし、controllerを作成するためには予めyo generate-angular
でAngularJS用リポジトリを作成しておく必要があります。
.
├── README.md
├── app
│ ├── 404.html
│ ├── favicon.ico
│ ├── images
│ │ └── yeoman.png
│ ├── index.html
│ ├── robots.txt
│ ├── scripts
│ │ ├── app.js
│ │ └── controllers
│ │ └── main.js
│ ├── styles
│ │ └── main.scss
│ └── views
│ └── main.html
├── bower.json
├── gulpfile.js
├── package.json
└── test
└── spec
└── controllers
└── main.js
YEOMANを使って高速にAngularJSプロジェクトを作る
YEOMANとは
YEOMANはWebアプリケーションジェネレータと呼ばれるツールの一つです。
新しいアプリケーションを作成する際に必要なディレクトリやコンポーネントを自動作成することができます。
Web開発を始める時、プロジェクトのディレクトリ構成やツールの導入の仕方で迷うことはよくあると思いますが、
YEOMANを使うことで、構成に迷うことなくプロジェクトをすぐに立ち上げることができます。
またYEOMANのディレクトリ構成がある種のスタンダードになりつつあるようなので、
既にあるプロジェクトにもYEOMANの構成を取り入れてみる、というのもありだと思います。
YEOMANを使ってみる
さっそくYEOMANを使ってみましょう。
環境はMac OS Xです。
Windowsの方はPowerSHellかcmderでお願いします。。。
先ずはnpm
を使い、コマンドツールyo
をインストールします。
$ npm install -g yo
このyo
コマンドを使って、以降プロジェクトのテンプレート作成等を行っていきます。
yo
をインストールしたら、次はWebアプリケーションジェネレータをインストールします。
$ npm install -g generator-[webapp]
[webapp]
の箇所には作成したいWebアプリケーションのジェネレータ名が入ります。
インストールできるジェネレータ一覧はこちら -> Generator
ジェネレータ一覧を見るとフレームワークの名前がちらほらと見えるので、
自分の作成したいWebアプリケーションで使うフレームワーク用ジェネレータを入れていきましょう。
今回はAngularJSのジェネレータをインストールしていきます。
$npm install -g generator-webapp
次に、プロジェクトのテンプレートを作成したいディレクトリに移動し、
以下のyo
コマンドを実行。
# ディレクトリ移動 $ cd yoman # テンプレート作成 $ yo angular
初めてyo
コマンドを実行する場合、匿名レポート提出許可のオプションが出てくると思いますがこちらはお好みでY
またはn
を入力。
? ========================================================================== We're constantly looking for ways to make yo better! May we anonymously report usage statistics to improve the tool over time? More info: https://github.com/yeoman/insight & http://yeoman.io ========================================================================== (Y/n)
次におじさんAAが出てきます。
同時に「Gruntの代わりにGulp使う?」と聞いてきますが、ここではy
を入力。
_-----_ | | ╭──────────────────────────╮ |--(o)--| │ Welcome to Yeoman, │ `---------´ │ ladies and gentlemen! │ ( _´U`_ ) ╰──────────────────────────╯ /___A___\ / | ~ | __'.___.'__ ´ ` |° ´ Y ` Out of the box I include Bootstrap and some AngularJS recommended modules. ? Would you like to use Gulp (experimental) instead of Grunt? Yes
ちなみにこのGruntおよび Gulpはタスクランナーと呼ばれるツールで、
Webアプリケーションの様々な処理をタスクという単位で自動実行するのに使います。
その後もYesを入力していきます。
# Sass : コンパイルするとcssになるスクリプト(Yes) ? Would you like to use Sass? Yes # Bootstrap : イケてる鉄板CSSライブラリ(Yes) ? Would you like to include Bootstrap? Yes # angular用ライブラリ群(Yes) ? Which modules would you like to include? angular-animate.js, angular-cookies.js, angular-resource.js, angular-route.js, angular-sanitize.js, angular-touch.js
最後に導入したいライブラリを選択してEnterを押すとプロジェクトの生成が開始されます。
.
├── README.md
├── app
│ ├── 404.html
│ ├── favicon.ico
│ ├── images
│ │ └── yeoman.png
│ ├── index.html
│ ├── robots.txt
│ ├── scripts
│ │ ├── app.js
│ │ └── controllers
│ │ └── main.js
│ ├── styles
│ │ └── main.scss
│ └── views
│ └── main.html
├── bower.json
├── gulpfile.js
├── package.json
└── test
└── spec
└── controllers
└── main.js
AngularJS Webアプリケーションプロジェクトのテンプレートができました!
YEOMANを使えば、新しいフレームワークを試したいときにも簡単に開発を始めることができそうですね。
またテンプレート作成時に導入されるツールの種類から「このフレームワークにはこういうツールを導入すると良いのかも」というように、必要なWeb開発ツールについて新しい示唆を得ることもできそうです。
【AngularJS】ルーティングを設定する
AngularJSはSPAを実装するフレームワークであるため、単一のページを読み込んだ後にクライアント側で柔軟に表示を切り替えていく機能を備えています。
AngularJSでは$routeProvider
を使うことによって、リクエストURL別にコントローラーやテンプレートを切り替えることができます。
ルーティングを設定
ルーティングの設定はconfig
メソッドを使ってやっていきます。
config
メソッドはAngularJSアプリケーションの前処理(configフェーズ)を記述するために使われます。
なお、configフェーズではServiceのインスタンスが生成されません。
// ルーティング情報を記述 angular.module('App') .config(function($routeProvider) { $routeProvider .when('/', { templateUrl: '../../views/index.html', controller: 'MainController' }) .when('/hoge', { templateUrl: '../../views/hoge.html', controller: 'HogeController' controllerAs: 'HogeCtrl' resolve: { currentHoge: 'currentHoge' } }) .otherwise({ redirectTo: '/' }); }]);
$routeProvider
のwhen
メソッドを呼び出し、リクエストURLと対応するHTMLファイル、Controllerなどを登録していきます。
パラメータ
templateUrl
パスが入力されたときに表示するHTMLテンプレートファイルです。
controller
表示するHTMLテンプレートファイルに対応するControllerです。
controllerAs
Controllerの別変数名を設定できます。Controllerの持つ変数時などに、この変数を使うことができます。
resolve
Promiseオブジェクトを返戻するサービス名を指定すると、 サービス内の全てのPromiseに対してresolveが呼ばれたときに、Promiseの値を注入します。
そのほか、下記のパラメータを設定できます。
- template : 文字列としてテンプレートを設定する
- redirectTo : リダイレクト先を設定する
- reloadOnSear : $location.search/hashが変更された時、設定したルーティング先を再読込するかどうか
- caseInsentiveMatch : ルーティング先の大文字/小文字を区別する
【AngularJS】Controller間で共有可能な値を定義する
AngularJSでは、Controller間で共有可能な値を定義する方法が二通りあります。
value
constant
value
value
メソッドを使うことで、Controller間で共有できる値を定義することができます。
定義した値はControllerの引数に設定することで使用可能になります。
FactoryやService内でも同様にして利用可能です。
// 値の定義 angular.module('MyApp',[]) .value("hogeStr", "hogehoge") .value("nHoge", 123) .value("isHoge", true) .value("hogeObj", {"hoge" : "1", "fuga" : "2"}); // 使用時はControllerの引数に渡す angular.module('MyApp') .controller('MyController', [ '$scope', 'hogeStr', 'nHoge', 'isHoge', 'hogeObj', function($scope, hogeStr, nHoge, isHoge, hogeObj) { console.log(hogeStr); // hogehoge console.log(nHoge); // 123 console.log(isHoge); // true console.log(hogeObj); // {hoge: "1", fuga: "2"} }]);
constant
value
メソッド同様に、constant
メソッドを使っても共有変数を定義することができます。
// 結果はvalueと同じ angular.module('MyApp',[]) .constant("hogeStr", "hogehoge") .constant("nHoge", 123) .constant("isHoge", true) .constant("hogeObj", {"hoge" : "1", "fuga" : "2"}) .controller('MyController', [ '$scope', 'hogeStr', 'nHoge', 'isHoge', 'hogeObj', function($scope, hogeStr, nHoge, isHoge, hogeObj) { console.log(hogeStr); // hogehoge console.log(nHoge); // 123 console.log(isHoge); // true console.log(hogeObj); // {hoge: "1", fuga: "2"} }]);
valueとconstantの違い
話が飛びますが、AngularJSはアプリケーションを実行する際config
とrun
と呼ばれる二つの工程を経由します。
config
フェーズではangular.configメソッドを用い、Providerと呼ばれるモジュールの設定変更を行います。
(Providerはサービスの挙動を変更するために用いられます)
config
フェーズではまだサービスがインスタンス化されていない状態なので、サービスを機能を利用することができません。
value
もサービスの一種であるため、config
フェーズでは使うことはできません。
一方でconstant
もサービスの一種なのですが、例外的にconfig
内で使用することができます。
そのためconfig
フェーズで共有変数を利用したい場合は、必然的にconstant
を利用することになります。
じゃあvalue
は使う意味ないじゃないかと思うかもしれませんが、
「constantはconfigフェーズでのみ利用する」「valueはrunフェーズ以降で利用する」のように、
各メソッドに意味を与えつつ使い分けるというやり方が可能です。
やっぱりconstant
だけで良い気がしてきた
参考文献
【AngularJS】AngularJSで動的にイベントハンドラを定義する
AngularJSのモジュールを使い、動的にイベントハンドラーを追加する方法メモ。
// controller angular.module('myApp',[]) .controller('myController',[ '$window', function($window){ // 画面全体に対するクリックリスナー angular.element($window).bind('click', function(){ console.log('click...'); }); // スクロールリスナー angular.element($window).bind('scroll', function(){ console.log('scrolling...'); }); // 組み込みの要素参照を使っても定義可能 angular.element(document.getElementById('hoge')).bind('click', function(){ console.log('click...'); }); } ]);
上記コードでは、windowオブジェクトに対してクリックイベントやスクロールイベントのリスナーを登録しています。
$window
AngularJS 1.2 日本語リファレンス | js STUDIOより
ブラウザのwindowオブジェクトを参照します。
JavaScript組み込みオブジェクトでもあるwindowへの参照をもつ、Angularの変数。
angular.element
素のDOM要素、またはHTML文字列をjQuery要素としてラップします。 もし、jQueryが利用可能であれば、angular.elementはjQuery関数へのエイリアスになります。 そうでなければ、angular.elementは、"jQuery lite"また は"jqLite"と呼ばれる、 Angular組み込みのjQueryのサブセットに委譲します。
JQueryが使える環境であれば、JQueryのラッパーになるようです。
使えない環境でもAngularJSに組み込まれている軽量なDOM操作ライブラリを使ってくれる模様。
angular.element.bind
要素に任意のイベントで実行させたい関数を紐づけます。
JQueryで書く場合
$('window').on('click', function(){ console.log("click..."); ); $('window').on('scroll', function(){ console.log("click..."); );
参考文献
【AngularJS】Viewにhtml文字列を挿入、htmlとしてレンダリングする
AngularJSを使ったフロント開発の中で、技術記事のAPIで取得したHTMLを画面に表示させたくなった
ときの処理をメモ。
ng-bind-html
でViewにhtml文字列をサニタイズされた形で挿入できます。
View
<!-- article.bodyプロパティにはHTMLが入っている--> <div ng-bind-html="article.body"></div>
// APIで記事を取得 articleService.getArticle().then(function(response) { // 記事情報 $scope.selectedArticle = response.data; }); };
実行結果
実際にはQiitaAPIを叩いてMarkdownをHTMLに変換して、マテリアルデザインにして・・・とか色々やっているのですが割愛。
ちゃんとHTMLの文章を挿入することができました。
ちなみにHTMLを普通の文字列としてViewに挿入する場合はng-bind
で可能。
参考文献
【AngularJS】既存のServiceを拡張した派生Serviceを定義する
AngularJSで既存のServiceが持つ機能を拡張させたServiceを定義したかったので、
以下のようにしてServiceを派生させてみました。
Service定義
"use strict"; // 基底Service(factory形式) angular.module('App') .factory('baseService',[ function(){ let service = { hoge: function(){ return 'hoge'; } }; return service; }]); // 派生Service angular.module('App') .factory('childService', [ 'baseService', function(baseService){ let service = { hoge: function(){ return 'hogehoge'; }, fuga: function(){ return 'fuga'; } }; // 二つのサービスを結合(基底サービスと一致するプロパティがある場合上書き) return Object.assign(Object.assign({}, baseService), service); }]);
実行
"use strict"; angular.module('App', []) .controller('MainController', [ 'childService', function(childService) { console.log(childService.hoge()); console.log(childService.fuga()); }]);
実行結果
hogehoge fuga
いわゆるコンポジット(プロパティではないので多分違いますが)のような形に落ち着きました。
派生Service内の実行関数の引数として基底Serviceをとり、基底Serviceで定義したserviceオブジェクトと、
派生Serviceで定義したserviceオブジェクトを結合しています。
両者が同じプロパティを保つ場合、派生側で上書きされるようにしました。
両者は継承関係にあるとは言えないので、派生という言い方も微妙かもしれません。。。