AngularJS で nl2br とか

AngularJS 1.2 で、サーバから取得した改行コード入りのテキストを、PHP で言うところの nl2br() を適用して <br> タグを含んだ HTML テキストに変換し、その HTML をエスケープさせずに Angular に出力してもらいたい。しかも、ループコンテキストの中で。
今回は何とか実装できたが 100% 忘れる自信があるので、メモしておく。

まずは nl2br のフィルター。そのくらい標準装備してくれよと思いつつ、探してみると angular-twig-pack というライブラリにまとめてあった。
nl2br フィルターはこれ。ちなみにドキュメントの Controller の部分は引数の順序が全部間違ってて、$filter('nl2br')('FR\nangular\nJS') が正しい。

次に HTML タグをエスケープさせない方法。これが Angular のバージョンによって変遷を辿っているようで、検索すると ngBindHtmlUnsafe ディレクティブを使うと書かれているページによく出くわすが、バージョン 1.2 ではこのディレクティブの記載がなくなっている。
で、今は$sce サービスと ngBundHtml ディレクトリを使うようだ。

最終的にできたコードが以下のようなもの。これが正しいやり方なのか今一つ自身が持てないけど、一応希望通りの挙動にはなった。

JavaScript

var myApp = angular.module('myApp', ['ngResource', 'twig']);

var MyCtrl = function($scope, $http, $sce, $filter) {

    $scope.items = [];

    $scope.getItem = function() {
        $http.get(url).
            success(function(data, status) {
                // data.item は改行コードを含んだテキスト
                $scope.items.push(
                    $sce.trustAsHtml( $filter('nl2br')(data.item) )
                );
            });
    };
}

HTML

<ol>
    <li ng-repeat="item in items track by $index">
        <p ng-bind-html="item"></p>
    </li>
</ol>

ngRepeat ディレクティブの中で track by $index が付いてないと、リストに同じ要素が含まれている場合にエラーになってしまう。ここもまだちゃんと調べてないので要調査。

Django のフィルターみたいに {{ item | nl2br | safe }} とできれば簡単なんだけど、そうはできないのかね?

Last updated on July 7, 2015