AngularJS

【Angular.js】ビュー変更(ルーティング切り替え)時のベストプラクティス。

HTML5モードと非HTML5モードの自動切り替えをAngular側にやってもらうためにも、aタグにリンクを埋め込むのではなく、$locationサービスを用いてルーティング変更を行うべき。

下記例。

コントローラー側に下記のようなメソッドを定義。

$scope.changeView = function(view){
    $location.path(view);
}

ビュー側から下記のようにして移動先のロケーションパスを渡せばOK。

<button ng-click="changeView('/about')">ほげ</button>

といった感じ。

 

【Angular.js】アニメーションの完了を検知して処理を実行する。

angualrのanimationは高速でクリックを繰り返したりすると、時々ng-animateクラスが削除され切らずにのこってしまい、表示がおかしくなる問題がある。
そこでアニメーションの終了を検知して、完了後自動でng-animateクラスを削除するように設定したらanimationの挙動を修正することが出来たのでメモ。

まずはanimation終了を検知するディレクティグを定義。

coreDirectives.directive('exShow', function($animate) {
    return {
        scope: {
            'exShow': '=',
            'afterShow': '&',
            'afterHide': '&'
        },
        link: function(scope, element) {
            scope.$watch('exShow', function(show, oldShow) {
                if (show) {
                    $animate.removeClass(element, 'ng-hide', scope.afterShow);
                }
                if (!show) {
                    $animate.addClass(element, 'ng-hide', scope.afterHide);
                }
            });
        }
    }
});

次にビュー側で用意したトリガーに関数をバインドする。

<div class="top-search-section" ex-show="sarchSection" after-hide="doneAnimate('top-search-section')"></div>

として、コントローラーでこうする。

$scope.toggleSearchSection = function() {
    $scope.sarchSection = $scope.sarchSection ? false : true;
}

$scope.doneAnimate = function(className) {
    $('.' + className).removeClass('ng-animate')
}

アニメーション終了後、doneAnimateが動作して、指定された要素の「ng-animate」クラスが削除されるという流れ。

 

【Angular.js】タグインプットを実装する。

type=textのような入力フォームでタグ風に入力させることが出来るプラグイン。

http://ngmodules.org/modules/ngTagsInput

デモはこちら。

http://mbenford.github.io/ngTagsInput/demos.html

ドキュメントは下記。

http://mbenford.github.io/ngTagsInput/documentation

設定も豊富にあるし、これはめちゃくちゃ便利だわ。

 

【Angular.js】表示する文字数を制限出来るangular-turncate。

例えばビュー側で何文字以降は「…」にしたいといった場合に便利。

ダウンロードとドキュメントは下記。

http://sparkalow.github.io/angular-truncate/

 

【Angular.js/bootstrap3】ng-repeatでrow、colを綺麗に出力させる。

完全に盲点だったんだけど、単純にブロックごとに分割されたオブジェクトをビューに渡してやればOK。

ビューはこんな感じ。

<div class="row" ng-repeat="row in rows">
    <div class="col-md-3" ng-repeat="col in row">
    </div>
</div>

てきな感じ。

下記エントリを見てハッとした。

http://stackoverflow.com/questions/11056819/how-would-i-use-angularjs-ng-repeat-with-twitter-bootstraps-scaffolding

 

【Angular.js】Node用のNicetimeライブラリをAngular用、かつ日本語化してみた。

Nicetimeは時間を渡すと○秒前とか○分前とかに変換してくれるライブラリ。
しかしネット上に転がっているもので日本語のものが無いので、日本語化&Angularのサービス化を

ベースにしたのは下記ライブラリ。というか秒カウントを追加した以外、英語の部分しか変更してない件。

https://github.com/robinduckett/nicetime

coreServices.service('niceTime', function() {
    return function(duration, to) {
        var nicetime = function(duration, to) {
            if (to == null) {
                  return niceify(duration);
              } else if (duration != null && to != null) {
                  var from = duration;
                  var to = to;
                  return niceify(to - from);
              } else if (duration == null && to != null) {
                  var from = new Date().getTime() / 1000;
                  var to = to;
                  return niceify(to - from);
              }
        }
        var niceify = function(duration) {
            var past = false;
            if (duration < 0) {
              past = true;
              duration = Math.abs(duration);
            }
            duration = new Number(duration).toFixed(2);
            
            var durstr = '';
            
            var second = 1,
                minute = second * 60,
                hour = minute * 60,
                day = hour * 24;
            if (duration < minute) {
                durstr = Math.ceil(duration) + '秒';
            } else if (duration < minute * 2) {
                durstr = '1分';
            } else if (duration < hour) {
                durstr = Math.floor(duration / minute) + '分';
            } else if (duration < hour * 2) {
                durstr = '1時間';
            } else if (duration < day) {
                durstr = Math.floor(duration / hour) + '時間';
            } else if (duration < day * 2) {
                durstr = '1日';
            } else if (duration < day * 365) {
                durstr = Math.floor(duration / day) + '日';
            } else {
                durstr = '1年以上';
            }
            
            if (past == true) durstr += '前';
            return durstr;
        }
        return nicetime(duration, to);
    }
});

使い方は下記の通り。
指定した時間からの経過時間を知りたい場合。

// 第1引数にnull、第2引数にターゲット時間の秒数を渡せばOK。
niceTime(null, createdAt.getTime()/1000);

その他の使い方は参考元ライブラリと同様なので、上記の公式リポジトリを参照されたし。

 

【Angular.js】aタグのhrefに変数でリンクを埋め込む際、勝手に「:unsafe」がついてしまう場合。

例えば「chrome-extension:」のような独自のプロトコルを埋め込もうとすると、Angularさんは未知のプロトコルとして、自動的に害のないセーフティーな文字列に置換してくれる。
しかしこういった外部アプリケーションをコールするような文字列を意図的に埋め込みたい場合、この機能はとても邪魔になる。

これを回避する方法は下記の通り。
「$compileProvider」を用いてhref属性に含められるプロトコルのホワイトリストを再定義してやればOK。

// 例えばchrome-extensionプロトコルを埋め込みたい場合は下記の通り。
app.config(['$compileProvider', function($compileProvider) {
    $compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|chrome-extension):/);
}]);

これでリンク属性に独自のプロトコルを埋め込むことが出来るようになる。

 

【Angular.js】Facebookのソーシャルパーツを出力してくれるAngularFacebook。

かなりお手軽にいいねボタンなどを出力することが可能。

リポジトリは下記。

https://github.com/boynux/AngularFacebook

例えば、いいねボタン、シェアボタンを出力したい場合は下記のように記述すればOK。

ライブラリを注入した後に、ビュー側でこうする。

<facebook app-id="InsertApplicationIdHnere"></facebook>
<facebook-like share="true" layout="button"></facebook-like>

めっちゃ簡単。