96 votes

angular ng-bind-html et les directives qu'il contient

Lien avec Plunker

J'ai un élément auquel je voudrais lier du html.

<div ng-bind-html="details" upper></div>

Cela fonctionne. Maintenant, avec cela, j'ai aussi une directive qui est liée au html lié :

$scope.details = 'Success! <a href="#/details/12" upper>details</a>'

Mais la directive upper avec le div et l'ancre ne sont pas évalués. Comment faire pour que cela fonctionne ?

187voto

vkammerer Points 436

J'étais également confronté à ce problème et après des heures de recherche sur internet, j'ai lu le commentaire de @Chandermani, qui s'est avéré être la solution. Vous devez appeler une directive 'compile' avec ce modèle :

HTML :

<div compile="details"></div>

JS :

.directive('compile', ['$compile', function ($compile) {
    return function(scope, element, attrs) {
        scope.$watch(
            function(scope) {
                // watch the 'compile' expression for changes
                return scope.$eval(attrs.compile);
            },
            function(value) {
                // when the 'compile' expression changes
                // assign it into the current DOM
                element.html(value);

                // compile the new DOM and link it to the current
                // scope.
                // NOTE: we only compile .childNodes so that
                // we don't get into infinite loop compiling ourselves
                $compile(element.contents())(scope);
            }
        );
    };
}])

Vous pouvez voir un travail le tripoter ici

36voto

user3075469 Points 71

Merci pour cette excellente réponse vkammerer. Une optimisation que je recommanderais est de ne plus faire de veille après que la compilation ait été exécutée une fois. Le $eval dans l'expression watch pourrait avoir des répercussions sur les performances.

    angular.module('vkApp')
  .directive('compile', ['$compile', function ($compile) {
      return function(scope, element, attrs) {
          var ensureCompileRunsOnce = scope.$watch(
            function(scope) {
               // watch the 'compile' expression for changes
              return scope.$eval(attrs.compile);
            },
            function(value) {
              // when the 'compile' expression changes
              // assign it into the current DOM
              element.html(value);

              // compile the new DOM and link it to the current
              // scope.
              // NOTE: we only compile .childNodes so that
              // we don't get into infinite loop compiling ourselves
              $compile(element.contents())(scope);

              // Use un-watch feature to ensure compilation happens only once.
              ensureCompileRunsOnce();
            }
        );
    };
}]);

Voici un violon bifurqué et mis à jour.

28voto

Joël Points 889

Ajoutez cette directive angular-bind-html-compile

.directive('bindHtmlCompile', ['$compile', function ($compile) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      scope.$watch(function () {
        return scope.$eval(attrs.bindHtmlCompile);
      }, function (value) {
        // Incase value is a TrustedValueHolderType, sometimes it
        // needs to be explicitly called into a string in order to
        // get the HTML string.
        element.html(value && value.toString());
        // If scope is provided use it, otherwise use parent scope
        var compileScope = scope;
        if (attrs.bindHtmlScope) {
          compileScope = scope.$eval(attrs.bindHtmlScope);
        }
        $compile(element.contents())(compileScope);
      });
    }
  };
}]);

Utilisez-le comme ceci :

<div bind-html-compile="data.content"></div>

Vraiment facile :)

13voto

apoplexy Points 33

Malheureusement, je n'ai pas assez de réputation pour faire des commentaires.

Je n'ai pas réussi à le faire fonctionner pendant des années. J'ai modifié mon ng-bind-html pour utiliser cette directive personnalisée, mais je n'ai pas réussi à supprimer la directive $scope.html = $sce.trustAsHtml($scope.html) qui était nécessaire pour que ng-bind-html fonctionne. Dès que je l'ai supprimé, la fonction de compilation a commencé à fonctionner.

6voto

MStrutt Points 369

Pour tous ceux qui traitent du contenu qui a déjà été soumis à des tests. $sce.trustAsHtml Voici ce que j'ai dû faire différemment

function(scope, element, attrs) {
    var ensureCompileRunsOnce = scope.$watch(function(scope) {
            return $sce.parseAsHtml(attrs.compile)(scope);
        },
        function(value) {
            // when the parsed expression changes assign it into the current DOM
            element.html(value);

            // compile the new DOM and link it to the current scope.
            $compile(element.contents())(scope);

            // Use un-watch feature to ensure compilation happens only once.
            ensureCompileRunsOnce();
        });
}

Ce n'est que le link de la directive car j'utilise une mise en page différente. Vous devrez injecter la directive $sce ainsi que $compile .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X