2015-07-27 15 views
8

Tôi đang cố gắng để khử trùng nội dung của một số lĩnh vực văn bản, tôi không thể sử dụng ng-bind-html vì nó phá vỡ hai cách ràng buộc (ng-model không hoạt động cùng lúc)

Kỳ lạ thay khi tôi áp dụng ng-bind-html đến một mô hình nó tạo ra một kết quả khác với khi tôi sử dụng $sanitize hoặc $sce bên trong chỉ thị.

Dưới đây là một ví dụ tôi tạo thành

http://plnkr.co/edit/iRvK4med8T9Xqs22BkOe?p=preview

vùng văn bản đầu tiên sử dụng ng-bind-html, thứ hai sử dụng $sanitize và thứ ba nên là mã cho các chỉ ng-bind-html như tôi tách ra khỏi Mã nguồn AngularJS.

" chỉ được sửa chữa thay đổi để " khi sử dụng ng-bind-html, trong hai ví dụ khác nó thay đổi để "

Làm thế nào tôi có thể nhân rộng các kết quả của ng-bind-html trong chỉ thị của tôi - trong khi vẫn giữ hai cách ràng buộc ?

angular.module('sanitizeExample', ['ngSanitize']) 
 
    .controller('ExampleController', ['$scope', '$sce', 
 
    function($scope, $sce) { 
 

 
     $scope.value = 'This in "quotes" for testing'; 
 
     $scope.model = 'This in "quotes" for testing'; 
 

 
    } 
 
    ]).directive('sanitize', ['$sanitize', '$parse', '$sce', 
 
    function($sanitize, $parse, $sce) { 
 
     return { 
 
     restrict: 'A', 
 
     replace: true, 
 
     scope: true, 
 
     link: function(scope, element, attrs) { 
 

 
      var process = function(input) { 
 
      return $sanitize(input); 
 
      //return $sce.getTrustedHtml(input); 
 
      }; 
 

 
      var processed = process(scope.model); 
 
      console.log(processed); // Output here = This in "quotes" for testing 
 
      $parse(attrs.ngModel).assign(scope, processed); 
 
      //element.html(processed); 
 
     } 
 
     }; 
 
    } 
 
    ]) 
 
    .directive('sanitizeBindHtml', ['$parse', '$sce', 
 
    function($parse, $sce) { 
 
     return { 
 
     restrict: 'A', 
 
     replace: true, 
 
     scope: true, 
 
     link: function(scope, element, attrs) { 
 

 
      var parsed = $parse(attrs.ngModel); 
 

 
      function getStringValue() { 
 
      var value = parsed(scope); 
 
      getStringValue.$$unwatch = parsed.$$unwatch; 
 
      return (value || '').toString(); 
 
      } 
 

 
      scope.$watch(getStringValue, function ngBindHtmlWatchAction(value) { 
 
      var processed = $sce.getTrustedHtml(parsed(scope)) || ''; 
 

 
      $parse(attrs.ngModel).assign(scope, processed) 
 
      }); 
 
     } 
 
     }; 
 
    } 
 
    ]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.min.js"></script> 
 
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-sanitize.js"></script> 
 

 
<!doctype html> 
 
<html lang="en"> 
 

 

 
<body ng-app="sanitizeExample"> 
 

 
    <div ng-controller="ExampleController"> 
 
    <textarea ng-bind-html="value"></textarea> 
 
    <br/>{{value}} 
 
    <br/> 
 
    <br/> 
 
    <textarea sanitize ng-model="model"></textarea> 
 
    <br/> 
 
    <br/> 
 
    <textarea sanitize-bind-html ng-model="model"></textarea> 
 

 
    </div> 
 
</body>

+0

Điều này thật thú vị.Lệnh 'ngModel' dường như đang gây ra các vấn đề ở đây cho bạn, và thiết lập' priority' sẽ không sửa chữa nó. Trong ví dụ cuối cùng của bạn, sao chép 'ngBindHtml', nếu bạn thay thế' ngModel' bằng một tên khác (ví dụ: 'bob',' bob = "model" '), nó sẽ hoạt động. http://plnkr.co/edit/eVA9lvMmwOcWKL1B2fjM?p=preview. Tương tự như chỉ thị thứ hai của bạn, ngoại trừ nó yêu cầu một vài thay đổi nhỏ khác: phân tích cú pháp. – DRobinson

+1

Tò mò để nghe câu trả lời đầy đủ từ ai đó có nhiều kinh nghiệm hơn, hoặc dành thời gian để tìm hiểu về chỉ thị 'ngModel'. Nếu điều đó không xảy ra, tôi sẽ đào sâu vào nguồn đó khi tôi có thêm một chút thời gian :). Hiện tại, như tôi đã đề cập, việc cập nhật một thuộc tính khác hoạt động cho chỉ thị khác của bạn, quá http://plnkr.co/edit/lVH1IQAhMfAot116xfiM?p=preview – DRobinson

+0

Tôi sẽ phải xem những gì tôi có thể tìm hiểu trên 'ngModel' khi tôi có cơ hội. Đó là một sự xấu hổ thay đổi thuộc tính không cho phép hai cách ràng buộc để hoạt động vẫn còn! – Amicable

Trả lời

2

Hóa ra như chúng ta mong đợi, các dịch vụ vệ sinh môi trường đang trở lại cùng một kết quả. Đặt một điểm ngắt bên trong ngBindHtmlDirective, Chúng ta có thể bước vào và xem những gì đang xảy ra. Chúng tôi đi sâu vào và kiểm tra các giá trị bên trong $SanitizeProvider. Giá trị của buf sẽ được trả lại cho ngBindHtmlDirective là:

này trong & # 34; trích & # 34; để thử nghiệm

Chính xác như chúng tôi nhận được khi gọi $ sanitize, vậy sự khác biệt thực sự là gì? Sự khác biệt thực sự là giữa innerHTML của một textbox và giá trị. Xem này example plunker. Bạn có thể thấy sự khác biệt giữa việc gọi hai phương thức khác nhau, với các cách khác nhau để thoát khỏi một dấu ngoặc kép. Tôi đã không đi đào mặc dù w3 spec hoặc mã trình duyệt, nhưng tôi giả định việc phân công innerHTML đang làm công việc bổ sung dưới mui xe của việc tạo ra một documentFragment, lấy textContent của nó, sau đó gán nó vào giá trị của hộp văn bản. Rõ ràng giá trị chỉ là lấy chuỗi và chèn nó như là.


Vì vậy, vấn đề với chỉ thị của bạn là gì? Tôi thấy rằng element.html(processed) là một nhận xét, nhưng bỏ ghi chú nó không có ảnh hưởng. Vâng sự thật là nó hoạt động trong một giây! Bước mặc dù với trình gỡ lỗi, giá trị của hộp văn bản được đặt chính xác, nhưng sau đó một chu kỳ $ digest được kích hoạt và thay đổi ngay lập tức! Sự thật là ngModelDirective đang cản trở, đặc biệt là $render function of the baseInputType. Chúng ta có thể thấy trong mã nó đang sử dụng phương thức element.val.

Làm cách nào để khắc phục điều này trong các chỉ thị? Yêu cầu ngModelController và ghi đè hàm $ render của nó để sử dụng phương thức element.html thay thế (example plunker).

// Add require to get the controller 
require: 'ngModel', 

// Controller is passed in as the 4th argument 
link: function(scope, element, attrs, ngModelCtrl) { 

// modify the $render function to process it as HTML 
ngModelCtrl.$render = function() { 
    element.html(ngModelCtrl.$isEmpty(ngModelCtrl.$viewValue) ? '' : ngModelCtrl.$viewValue); 
}; 
Các vấn đề liên quan