文字列に「&」と「>」の文字を含めることができるユースケースがあります。例えば。ジョンソン&ジョンソン、value > 3
。したがって、サーバーからの応答はエンコードされていますが、値は 'value&ampgt;になります。 3 '。
ng-bind
は以下をサポートしていません:
value > 3
はngBind
に対してレンダリングされますが、ブラウザはvalue > 3
と同じコンテンツをレンダリングします。
Ng:bind <div ng-bind="model"></div>
Ng:bind-html <div ng-bind-html="model"></div>
<div> From Div: value > </div>
このデフォルトのブラウザ動作がng-bind
に存在しないのはなぜですか? ng-bind-html
(値<
に問題があり、htmlではない)またはng-bind-unsafe-html
を使用したくない。
私のアプリケーションには、アプリケーションのさまざまな部分に表示される動的なKey-Valueフィールドがあります。したがって、ngBind
を使用するよりも、別のディレクティブまたはデコレータを使用してすべての文字列フィールドを表示するために、追加のオーバーヘッドが必要になります。
質問:
1)追加のディレクティブを使用せずに同じことを行う他の方法はありますか、またはこれはエンコードされたデータを処理する正しい方法ですか?
2)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つのオプションがあります。
これはですHTML:
>
HTMLタグがなくても、HTMLのままです。 ng-bind
を使用する場合、サーバーはエンコードされていないテキストを返す必要があります。つまり、>
ではなく>
になります。
ng-bind-html
を使用するか、サーバーを変更して、最初にHTMLエンコードせずにプレーンテキストを返します。
編集:JavaScriptでの>
および>
の使用法を示す簡単なデモ:
div1.innerHTML = ">"; // write HTML
div2.textContent = ">"; // write plain text
console.log(div1.innerHTML === div2.innerHTML);
console.log(div1.textContent === div2.textContent);
ng-bindは.text()メソッドを使用してテキストを置き換えます。コードにHTMLマークアップである_>
_が含まれている場合、ng-bindによって正しくレンダリングされません。実際にはHTMLコンテンツを入力しているため、この場所ではng-bind-htmlを使用する必要があります。それ以外の場合は、>を正規表現で「>」に置き換えることができます。
ex:-model = model.replace(/>/g, '>');
ただし、この場合、ng-bind-htmlはすでに問題なく機能しているため、不要なすべてのHTMLマークアップを置き換える必要があります。
はい、フィルターで「装飾」しましょう:
.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
そのようなユースケースで利用できるngBindHtmlUnsafeという名前のディレクティブを覚えています。
http://code.angularjs.org/1.0.8/docs/api/ng.directive:ngBindHtmlUnsafe
こちらをご参照ください。これが後の不安定リリースで利用可能かどうかは不明です。これは、入手可能な最新の安定版リリースへのリンクです。
なぜ$ sce.trustAsHtmlを使用しないのですか?