web-dev-qa-db-ja.com

AngularJsのng-bindでのエスケープ&>文字

文字列に「&」と「>」の文字を含めることができるユースケースがあります。例えば。ジョンソン&ジョンソン、value > 3。したがって、サーバーからの応答はエンコードされていますが、値は 'value&ampgt;になります。 3 '。

ng-bindは以下をサポートしていません:

value > 3ngBindに対してレンダリングされますが、ブラウザはvalue > 3と同じコンテンツをレンダリングします。

http://jsfiddle.net/HKahG/2/

Ng:bind <div ng-bind="model"></div> 
Ng:bind-html <div ng-bind-html="model"></div>
<div> From Div: value &gt; </div>

このデフォルトのブラウザ動作がng-bindに存在しないのはなぜですか? ng-bind-html(値<に問題があり、htmlではない)またはng-bind-unsafe-htmlを使用したくない。

私のアプリケーションには、アプリケーションのさまざまな部分に表示される動的なKey-Valueフィールドがあります。したがって、ngBindを使用するよりも、別のディレクティブまたはデコレータを使用してすべての文字列フィールドを表示するために、追加のオーバーヘッドが必要になります。

質問:

1)追加のディレクティブを使用せずに同じことを行う他の方法はありますか、またはこれはエンコードされたデータを処理する正しい方法ですか?

2)ng-bindの動作をオーバーライドしたり、デフォルトで装飾したりできますか?

18
DarkKnight

[〜#〜]編集[〜#〜]:回答の一番下に移動して、最適なバージョンを取得してください。答えは時系列です。最後に、数回繰り返して最適なコードを取得しました。ありがとうございました。

  • デフォルトでng-bindの動作をオーバーライドしたり、装飾したりできますか?

はい。私はng-bindを希望どおりに動作させる非常に単純な実装を行いました。ええと...これがあなたの望んでいるものかどうかはわかりませんが、少なくとも私があなたが望んでいることはわかっています。

作業フィドル: http://jsfiddle.net/93QQM/

そしてここにコードがあります:

module.directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
            return { 
                pre: function(scope) {
                    scope.myBind = function(text) {
                        return angular.element('<div>' + text + '</div>').text();
                    }
                }
            };
        }
    }
});

これは厳密には「追加のディレクティブ」ではありません。これは「ng-bindの動作をオーバーライドする」方法です。新しいディレクティブを追加するのではなく、既存のngBindディレクティブの動作を拡張するだけです。

compile関数で、ng-bind属性の値を変更して、関数呼び出しにラップします。これにより、元のモデル値にアクセスできるようになり、変更された値を返すことができます。

リンク前のフェーズでスコープを介して関数を使用できるようにします。これは、リンク後のフェーズでこれを行うと、関数は元のngBindディレクティブが属性から値を取得しました(関数が見つからないため、空の文字列になります)。

myBind関数はシンプルでスマートです。これは要素を作成し、テキストが変更されずに-要素本体として使用され、text関数を通じてただちに取得されます-これは「ブラウザがレンダリングする」コンテンツと同じです。

このように、<div ng-bind="model.content" />のように、通常どおりngBindを使用できますが、この動作は変更されています。


改良版

Ng [Bind]が適用されるすべてのスコープにmyBind関数をアタッチする代わりに、すべての事前リンク段階で$rootScopeに一度だけアタッチして、すべてのスコープですぐに使用できるようにすることができます。

新しい作業フィドル: http://jsfiddle.net/EUqP9/

新しいコード:

module.directive('ngBind', ['$rootScope', function($rootScope) {
    $rootScope.myBind = function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind = 'myBind(' + tAttrs.ngBind + ')';
        }
    };
}]);

以前のバージョンよりもずっときれいです!もちろん、myBind関数名を他の任意の名前に変更できます。機能の「コスト」は次のとおりです。この単純な関数をルートスコープに追加します-価格に見合うかどうかはユーザー次第です。


さらに別のバージョン

Chemivの回答の影響...関数をスコープから削除して、代わりにフィルターにしてみませんか?それも動作します。

さらに別の新しいフィドル: http://jsfiddle.net/hQJaZ/

そして新しいコード:

module.filter('decode', function() {
    return function(text) {
        return angular.element('<div>' + text + '</div>').text();
    };
}).directive('ngBind', function() {
    return {
        compile: function(tElement, tAttrs) {
            tAttrs.ngBind += '|decode';
        }
    };
});

これで、メニューから選択する3つのオプションがあります。

14
J. Bruni

これはですHTML:

&gt;

HTMLタグがなくても、HTMLのままです。 ng-bindを使用する場合、サーバーはエンコードされていないテキストを返す必要があります。つまり、>ではなく&gt;になります。

ng-bind-htmlを使用するか、サーバーを変更して、最初にHTMLエンコードせずにプレーンテキストを返します。

編集:JavaScriptでの&gt;および>の使用法を示す簡単なデモ:

div1.innerHTML = "&gt;";  // write HTML
div2.textContent = ">";   // write plain text
console.log(div1.innerHTML === div2.innerHTML);
console.log(div1.textContent === div2.textContent);

http://jsfiddle.net/XhEcV/

12
gilly3

ng-bindは.text()メソッドを使用してテキストを置き換えます。コードにHTMLマークアップである_&gt;_が含まれている場合、ng-bindによって正しくレンダリングされません。実際にはHTMLコンテンツを入力しているため、この場所ではng-bind-htmlを使用する必要があります。それ以外の場合は、>を正規表現で「>」に置き換えることができます。

ex:-model = model.replace(/&gt;/g, '>');

ただし、この場合、ng-bind-htmlはすでに問題なく機能しているため、不要なすべてのHTMLマークアップを置き換える必要があります。

6
Shreyance Jain

はい、フィルターで「装飾」しましょう:

.filter("decode",function(){
    return function(str){         
      var el = document.createElement("div");
      el.innerHTML = str;
      str =   el.textContent || el.innerText;
      return str;        
    }
});

次のように使用します:<div ng-bind="model|decode"></div>

作業例: http://jsfiddle.net/HKahG/5/

この答えに触発された: https://stackoverflow.com/a/784698/120661

5
Cherniv

そのようなユースケースで利用できるngBindHtmlUnsafeという名前のディレクティブを覚えています。

http://code.angularjs.org/1.0.8/docs/api/ng.directive:ngBindHtmlUnsafe

こちらをご参照ください。これが後の不安定リリースで利用可能かどうかは不明です。これは、入手可能な最新の安定版リリースへのリンクです。

1
Arshabh Agarwal

なぜ$ sce.trustAsHtmlを使用しないのですか?

0
Bob Barker