góc ng-bind-html và chỉ thị bên trong nó


96

Liên kết Plunker

Tôi có một phần tử mà tôi muốn liên kết html với nó.

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

Điều đó hoạt động. Bây giờ, cùng với nó, tôi cũng có một chỉ thị được liên kết với html bị ràng buộc:

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

Nhưng chỉ thị uppervới div và anchor không đánh giá. Làm cách nào để làm cho nó hoạt động?


3
Nhìn vào câu trả lời của tôi ở đây stackoverflow.com/questions/17343696/...
Chandermani

@Chandermani không sử dụng chính xác chỉ thị bên trong ng-bind-html-không an toàn mà sử dụng bộ lọc. Nhưng nó sẽ làm được, tôi vừa tạo một bộ lọc và chuyển tới chỉ thị. Cảm ơn!
Amitava

@SamSerious bạn có thể chỉ ra cách bạn đã làm những gì bạn đã làm cho các bộ lọc không?
CMCDragonkai

các giải pháp trên không xử lý nhiều thay đổi giá trị một giải pháp tốt hơn stackoverflow.com/a/25516311/3343425
fghibellini

Câu trả lời:


188

Tôi cũng đang đối mặt với vấn đề này và sau hàng giờ tìm kiếm trên internet, tôi đã đọc được bình luận của @ Chandermani, được chứng minh là giải pháp. Bạn cần gọi một chỉ thị 'biên dịch' với mẫu này:

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

Bạn có thể xem một cách làm việc của nó ở đây


1
Trong dòng số 2, tức là. function(scope, element, attrs), Nơi mà bạn đã nhận được từ những ba đối số, phạm vi , yếu tốattrs ?
spaffy

1
@spaffy - chúng là một phần của chữ ký của Angular framework cho thuộc linktính. Chúng sẽ được chuyển tự động mỗi khi linkđược Angular framework gọi. Chúng sẽ luôn có sẵn.
Ben

1
Làm tốt. Bạn đã tiết kiệm cho tôi những giờ tìm kiếm tương tự. Tôi đang lấy nội dung từ API REST của chế độ xem SharePoint, bản thân nó chứa đánh dấu Angular chẳng hạn như ng-repeat. Chỉ thị của bạn đã làm cho tất cả hoạt động. Cảm ơn!
Phil Nicholas

Cảm ơn chỉ thị của bạn, nó đã khắc phục sự cố mà tôi đang gặp phải. Bây giờ mã góc được biên dịch nhưng quá nhiều lần. Một ng-lặp lại với 3 đối tượng biến thành các giá trị giống nhau, mỗi giá trị chỉ 3x. Có chuyện gì xảy ra ở đây?
Jason

2
Nếu bạn đang sử dụng $sce.trustAsHtmltừ một hàm khác để tạo HTML sẽ được "biên dịch" với chỉ thị này, bạn nên xóa nó. Nhờ @apoplexy
Burak Tokak

36

Cảm ơn câu trả lời tuyệt vời vkammerer. Một tối ưu hóa mà tôi muốn giới thiệu là hủy xem sau khi quá trình biên dịch chạy một lần. $ Eval trong biểu thức đồng hồ có thể có ý nghĩa về hiệu suất.

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

Đây là một trò chơi được phân nhánh và cập nhật.


Tôi có thể làm ngược lại cho nó không?
Sanyam Jain

đây không phải là làm việc trong phản ứng của ajax nhưng công việc trả lời chấp nhận
foozhan

1
Cảnh báo: Câu đố cho câu trả lời này hoạt động, nhưng .directive()mã trong mã được đăng trong câu trả lời thì không.
Phil Nicholas

cái này đã làm việc cho tôi. câu trả lời được lựa chọn sẽ kích hoạt "Lỗi: $ rootScope: infdig Infinite $ digest Loop"
Gabriel Andrei

Bạn không cần hết hạn $eval- bạn chỉ có thể sử dụng attrs.compiletrực tiếp thay cho chức năng ẩn danh đã theo dõi. Nếu bạn chỉ cung cấp một biểu thức chuỗi, thì góc độ vẫn sẽ gọi $evalnó.
Dan King,

28

Thêm chỉ thị này angle-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);
      });
    }
  };
}]);

Sử dụng nó như thế này:

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

Thật sự dễ dàng :)


1
Hãy cẩn thận, nếu bạn chuyển một cái gì đó như sau: "$ scope.loadContent = function () {return $ domains.trustAsHtml (request ('html / main-content.html'));};" với nó, bạn có thể nhận được vòng lặp thông báo vô hạn. Nếu không có trustAsHtml nó hoạt động.
Lakatos Gyula

13

Thật không may, tôi không có đủ danh tiếng để bình luận.

Tôi không thể làm cho điều này để làm việc cho nhiều tuổi. Tôi đã sửa đổi ng-bind-htmlmã của mình để sử dụng chỉ thị tùy chỉnh này, nhưng tôi không xóa $scope.html = $sce.trustAsHtml($scope.html)được lệnh bắt buộc để ng-bind-html hoạt động. Ngay sau khi tôi loại bỏ điều này, chức năng biên dịch bắt đầu hoạt động.


6

Đối với bất kỳ ai xử lý nội dung đã được chạy qua $sce.trustAsHtmlđây là điều tôi phải làm khác đi

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

Đây chỉ là một linkphần của chỉ thị vì tôi đang sử dụng một bố cục khác. Bạn cũng sẽ cần phải tiêm $scedịch vụ $compile.


-2

Giải pháp tốt nhất mà tôi đã tìm thấy! Tôi đã sao chép nó và nó hoạt động chính xác như tôi cần. Cảm ơn cảm ơn cảm ơn ...

trong chức năng liên kết chỉ thị tôi có

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

và trong mẫu chỉ thị:

<span compile="renderingElement"></span>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.