각도 ng-bind-html 및 지시문


96

플 런커 링크

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

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

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

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

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


3
여기 내 대답을보세요 stackoverflow.com/questions/17343696/…
Chandermani

@Chandermani는 ng-bind-html-unsafe 내부의 지시문을 정확히 사용하지 않고 필터를 사용합니다. 그러나 그렇게 할 것입니다. 방금 필터를 만들고 지시문에 전달했습니다. 감사!
Amitava

@SamSerious 당신은 필터를 어떻게했는지 보여줄 수 있습니까?
CMCDragonkai 2013 년

위의 솔루션은 값의 여러 변화에게 더 나은 솔루션을 처리하지 않는 stackoverflow.com/a/25516311/3343425
fghibellini

답변:


188

나는 또한이 문제에 직면하고 인터넷을 검색 한 후 @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);
            }
        );
    };
}])

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


1
라인 # 2, 즉. function(scope, element, attrs)여기서 당신은 그 세 가지 인수에서 얻을 않았다 범위 , 요소바인드합니다 ?
spaffy

1
@spaffy- link속성에 대한 Angular 프레임 워크 서명의 일부입니다 . linkAngular 프레임 워크에서를 호출 할 때마다 자동으로 전달됩니다 . 항상 사용할 수 있습니다.
Ben

1
잘 했어. 당신은 저와 같은 시간의 검색을 구했습니다. ng-repeat와 같은 Angular 태그가 포함 된 SharePoint보기 REST API에서 콘텐츠를 가져옵니다. 당신의 지시로 모든 것이 작동했습니다. 감사!
Phil Nicholas

당신의 지시에 감사드립니다. 그것은 내가 가진 문제를 해결했습니다. 이제 각도 코드가 컴파일되지만 너무 많이 컴파일됩니다. 3 개의 개체가있는 ng-repeat는 각각 3 배의 동일한 값으로 바뀝니다. 여기서 뭐가 잘못 됐나요?
Jason

2
당신이 사용하고있는 경우 $sce.trustAsHtml이 지시어로 "컴파일"될 HTML을 생성하는 또 다른 함수에서, 당신은 그것을 제거해야합니다. 감사합니다 @apoplexy
Burak Tokak

36

훌륭한 답변 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();
            }
        );
    };
}]);

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


그 반대도 가능합니까?
Sanyam Jain

이 아약스의 응답 작업 만 허용 대답 작동하지 않습니다
foozhan

1
경고 :이 답변의 바이올린은 작동하지만 .directive()답변에 게시 된 코드의 코드는 작동하지 않습니다.
Phil Nicholas

이것은 나를 위해 일했습니다. 선택한 대답은 "infdig 무한 $ 다이제스트 루프 : $ rootScope 오류"가 발생하게
가브리엘 안드레이에게

설명이 필요하지 않습니다 . 감시 된 익명 함수 대신 직접 $eval사용할 수 있습니다 attrs.compile. 문자열 표현식 만 제공하면 angular가이를 호출 $eval합니다.
Dan King

28

이 지시문 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);
      });
    }
  };
}]);

다음과 같이 사용하십시오.

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

정말 쉽습니다 :)


1
다음과 같이 전달하는 경우주의하십시오. "$ scope.loadContent = function () {return $ sce.trustAsHtml (require ( 'html / main-content.html'));};" 그것에 무한 다이제스트 루프를 얻을 수 있습니다. trustAsHtml 없이는 작동합니다.
Lakatos Gyula 2015

13

불행히도 저는 논평 할만한 평판이 충분하지 않습니다.

나는 이것을 오랫동안 작동시킬 수 없었다. ng-bind-html이 사용자 지정 지시문을 사용하도록 코드를 수정 했지만 $scope.html = $sce.trustAsHtml($scope.html)ng-bind-html이 작동하는 데 필요한 코드를 제거하지 못했습니다 . 이것을 제거하자마자 컴파일 기능이 작동하기 시작했습니다.


6

이미 $sce.trustAsHtml여기 에서 실행 된 콘텐츠를 다루는 사람 은 내가 다르게해야 할 일입니다.

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

이것은 link다른 레이아웃을 사용하고 있기 때문에 지시문 의 일부일 뿐입니다 . 당신은 주입해야합니다 $sce뿐만 아니라 같은 서비스를 $compile.


-2

내가 찾은 최고의 솔루션! 나는 그것을 복사했고 그것은 내가 필요로하는대로 정확하게 작동합니다. 고마워, 고마워, 고마워 ...

지시어 링크 기능에서

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

그리고 지시어 템플릿에서 :

<span compile="renderingElement"></span>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.