Echapper &> caractères dans ng-bind dans AngularJs

J'ai un cas d'utilisation, où nous pouvons avoir des caractères '&' et '>' dans une chaîne. par exemple. Johnson & Johnson, value > 3 . Donc, alors que la réponse du serveur est codée, la valeur devient alors 'value & ampgt; 3 '.

ng-bind ne prend pas en charge les éléments suivants:

value > 3 value > 3 sera rendu pour ngBind , alors que le navigateur ngBind le même contenu que la 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> 

Pourquoi ce comportement de navigateur par défaut n'est pas présent dans ng-bind ? Je ne veux pas utiliser ng-bind-html (a des problèmes avec la valeur < et ce n'est pas un html) ou ng-bind-unsafe-html .

Mon application comporte des champs de valeurs clés dynamiques qui seront affichés dans différentes parties de l'application. Il faudra donc des frais généraux supplémentaires pour utiliser une directive ou un décorateur séparé pour afficher tous les champs de chaîne que d'utiliser ngBind .

Des questions:

1) Y a-t-il une autre façon de faire de même sans utiliser une directive supplémentaire, ou est-ce la bonne façon de gérer les données codées?

2) Puis-je remplacer le comportement de ng-bind ou le décorer par défaut?

EDIT : s'il vous plaît, allez directement au bas de la réponse pour obtenir la meilleure version; La réponse est chronologique; J'ai obtenu le code optimal après quelques itérations, à la fin. Je vous remercie.

  • Puis-je annuler le comportement de ng-bind ou le décorer par défaut?

Oui. J'ai fait une mise en œuvre très simple qui permet à ng-bind de se comporter comme vous le souhaitez. Eh bien … Je ne sais pas si c'est exactement ce que vous voulez, mais au moins, c'est ce que j'ai compris.

Violon de travail: http://jsfiddle.net/93QQM/

Et voici le code:

 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(); } } }; } } }); 

Ce n'est pas exactement une "directive supplémentaire" – c'est la façon de "neutraliser le comportement de ng-bind". Il n'ajoute pas une nouvelle directive, il étend simplement le comportement de la directive ngBind existante.

Lors de la fonction de compilation , nous modifions la valeur de l'attribut ng-bind , l'enrouler dans un appel de fonction. Avec cela, nous avons accès à la valeur du modèle d'origine et la possibilité de le modifier.

Nous rendons la fonction disponible dans la portée de la phase de pré-liaison, car si nous le faisons dans la phase de post-liaison, la fonction ne sera disponible qu'après que la directive ngBind d'origine aura récupéré la valeur de l'attribut (qui sera une Chaîne vide, car la fonction ne sera pas trouvée).

La fonction myBind est simple et intelligente: elle crée un élément et le texte est utilisé – inchangé – en tant que corps d'élément, pour être récupéré immédiatement à travers la fonction de text – qui renverra le contenu juste comme "le navigateur le rend".

De cette façon, vous pouvez utiliser ngBind comme d'habitude, comme <div ng-bind="model.content" /> , mais ont ce comportement modifié.


Version améliorée

Au lieu de joindre la fonction myBind à chaque champ d'application où ngBind est appliqué, à chaque phase de pré-liaison, nous ne pouvons l'attacher qu'une seule fois à $rootScope , ce qui la rend immédiatement disponible pour toutes les étendues.

Nouveau violon de travail: http://jsfiddle.net/EUqP9/

Nouveau code:

 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 + ')'; } }; }]); 

Beaucoup plus propre que la version précédente! Bien sûr, vous pouvez changer le nom de la fonction myBind à tout autre nom que vous voulez. Le «coût» de la fonctionnalité est le suivant: ajoutez cette fonction simple à la portée de la racine: vous devez décider s'il vaut le prix.


Encore une autre version

Influencé par la réponse de Chemiv … pourquoi ne pas supprimer la fonction de n'importe quelle portée et en faire un filtre à la place? Il fonctionne également.

Encore une nouvelle violon de travail: http://jsfiddle.net/hQJaZ/

Et le nouveau code:

 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'; } }; }); 

Maintenant, vous avez trois options à choisir dans le menu.

Ceci est HTML:

 &gt; 

Il peut ne pas avoir de balises HTML, mais c'est toujours HTML. Si vous souhaitez utiliser ng-bind , votre serveur doit retourner le texte non codé. C'est-à-dire, au lieu de &gt; .

Utilisez ng-bind-html ou modifiez votre serveur pour renvoyer du texte sans html en l'encodant d'abord.

Edit: Démo rapide qui illustre l'utilisation de &gt; Et > en JavaScript:

 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/

Ng-bind utilise la méthode .text () pour remplacer le texte et pendant que votre code contient &gt; Qui est un balisage HTML, il n'est pas correctement rendu par ng-bind. Vous devez utiliser ng-bind-html dans cet endroit, car vous entrez effectivement dans le contenu HTML. Sinon, vous pouvez remplacer> par regex par '>'.

Ex: – model = model.replace(/&gt;/g, '>');

Mais dans ce cas, vous devez remplacer toutes les balises HTML qui ne sont pas nécessaires puisque ng-bind-html fonctionne déjà bien dans votre cas.

Oui, on le "décorer" avec un filtre:

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

Et utilisez-le comme: <div ng-bind="model|decode"></div>

Exemple de travail: http://jsfiddle.net/HKahG/5/

Inspiré par cette réponse: https://stackoverflow.com/a/784698/1206613

Je me souviens d'une directive nommée ngBindHtmlUnsafe disponible pour ces cas d'utilisation.

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

Veuillez vous référer à ceci. Je ne sais pas si cela est disponible dans les versions ultérieures instables. Ceci est un lien vers la dernière version stable disponible.

Pourquoi ne pas utiliser seulement $ sce.trustAsHtml?