@peccul is peccu

(love peccu '(emacs lisp cat outdoor bicycle mac linux coffee))

AngularJSでのはまりどころ3選

AngularJSを初めたての頃、アホみたいなはまり方をした。 わかってしまえば当たり前なだけに、調べても分かりにくかったので恥さらしに記録する。

こんなミスを起こすと、気付くまでは動かない意味がわからなかった。

  • scriptタグを忘れる
  • モジュールを毎回生成してしまう
  • パラメータのIDを変えてしまった

scriptタグを忘れる

こんなエラーが出る。当たり前だけどなんで未定義になるのかわからなかった。

angular.js:11607Error: [ng:areq] Argument 'HogeCtrl' is not a function, got undefined

コントローラの名前を変えたりすると、起こりがち。あと、ファイルをフォルダに移動したりすると。

index.htmlにscriptタグ書きましょう

モジュールを毎回生成してしまう

モジュール名の意味もよくわかってなかった。

Error: [$injector:unpr] Unknown provider: CoolServiceProvider <- CoolService <- SomeCoolCtrl

こんなエラーとかでたりする。

ググって出てくるサンプルコードが、たいてい下の形になっていて真似していろんなファイルでangular.moduleの第二引数まで書いてしまった。

angular.module('SomeCoolApp', ['coolModule'])
  .config(...)
  .controller(...)
  .factory('CoolService', function(){
    coolFunction();
  });

これをすると毎回モジュールを生成してしまうから、解決するためにモジュール名をファイルごとに変えたりして、 泥沼にはまっていった。

Yeomanのgenerate-angularを使っていると、コントローラ、サービス、フィルタ、ディレクティブなどを全部別のファイルに分けてくれるので、 自動生成された部分を下手にいじるとはまる。

ググって出てきたコードのどこが必要なのか見極める必要がある。

こんな感じに書くと動く。

angular.module('SomeCoolApp')
  .factory('CoolService', function(){
    coolFunction();
  });

パラメータのIDを変えてしまった

これはチーム開発してる時。

ルーティングを別のメンバが調整してくれたときにパラメータの名前を変えていた。 サービスで参照するときに名前がなくて怒られる。

その怒られる場所がモックで500エラー。

変更前。ItemLoaderが$resourceのgetをつかってアイテムを1件取得する。MultiItemLoaderが$resourceのqueryを使って一覧取得する。 APIはRESTに従っていて、item.jsonで一覧取得、item/id.jsonで1件取得できる状態です。

angular.module('SomeCoolApp')
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/item/:itemId', {
        resolve: {
          item: ['ItemLoader', function(ItemLoader) {
            return new ItemLoader();
          }]
        },
        templateUrl: 'views/item/view.html',
        controller: 'ItemViewCtrl'
      })
      .when('/item', {
        resolve: {
          items: ['MultiItemLoader', function(MultiItemLoader) {
            return new MultiItemLoader();
          }]
        },
        templateUrl: 'views/item.html',
        controller: 'ItemCtrl'
      });

変更後。 item/:itemIditem/:id になる。

angular.module('SomeCoolApp')
  .config(['$routeProvider', function($routeProvider) {
    $routeProvider
      .when('/item/:id', {
        resolve: {
          item: ['ItemLoader', function(ItemLoader) {
            return new ItemLoader();
          }]
        },
        templateUrl: 'views/item/view.html',
        controller: 'ItemViewCtrl'
      })
      .when('/item', {
        resolve: {
          items: ['MultiItemLoader', function(MultiItemLoader) {
            return new MultiItemLoader();
          }]
        },
        templateUrl: 'views/item.html',
        controller: 'ItemCtrl'
      });

結果。

ItemLoaderで$route.current.params.itemIdが参照できないので、$resourceのgetにidが渡らない

REST APIの1件取得ではなく一覧取得が呼ばれる

→サーバーでエラー。

これも見つけにくかったので記録しておこうかと。