developer tip

각도 ng-bind-html 및 지시문

optionbox 2020. 8. 26. 07:48
반응형

각도 ng-bind-html 및 지시문


플 런커 링크

html을 바인딩하고 싶은 요소가 있습니다.

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

작동합니다. 이제 그와 함께 바인딩 된 html에 바인딩 된 지시문도 있습니다.

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

그러나 upperdiv 및 anchor가 있는 지시문 은 평가되지 않습니다. 어떻게 작동합니까?


나는 또한이 문제에 직면하고 인터넷을 검색 한 후 @Chandermani의 의견을 읽었으며 해결책이되었습니다. 다음 패턴으로 '컴파일'지시문을 호출해야합니다.

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

여기 에서 작동하는 바이올린을 볼 수 있습니다.


훌륭한 답변 vkammerer에 감사드립니다. 내가 권장하는 최적화 중 하나는 컴파일이 한 번 실행 된 후 감시 해제하는 것입니다. watch 표현식 내의 $ eval은 성능에 영향을 미칠 수 있습니다.

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

다음은 분기되고 업데이트 된 바이올린입니다.


Add this 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);
      });
    }
  };
}]);

Use it like this :

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

Really easy :)


Unfortunately I don't have enough reputation to comment.

I could not get this to work for ages. I modified my ng-bind-html code to use this custom directive, but I failed to remove the $scope.html = $sce.trustAsHtml($scope.html) that was required for ng-bind-html to work. As soon as I removed this, the compile function started to work.


For anyone dealing with content that has already been run through $sce.trustAsHtml here is what I had to do differently

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

This is only the link portion of the directive as I'm using a different layout. You will need to inject the $sce service as well as $compile.


Best solution what I've found! I copied it and it work's exactly as I needed. Thanks, thanks, thanks ...

in directive link function I have

app.directive('element',function($compile){
  .
  .
     var addXml = function(){
     var el = $compile('<xml-definitions definitions="definitions" />')($scope);
     $scope.renderingElement = el.html();
     }
  .
  .

and in directive template:

<span compile="renderingElement"></span>

참고URL : https://stackoverflow.com/questions/17417607/angular-ng-bind-html-and-directive-within-it

반응형