2015-07-27 3 views
8

Я пытаюсь дезинфицировать содержимое некоторых текстовых областей, я не могу использовать ng-bind-html, потому что он нарушает два способа связывания (ng-model не работает одновременно)

Как ни странно, когда я применяю ng-bind-html к модели он производит другой результат, когда я использую $sanitize или $sce внутри директивы.

Вот пример я сделал

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

Первая текстовая область использует ng-bind-html, вторые использует $sanitize и третий должен быть кодом для директивы нг-связывать-HTML, как я вырван из Исходный код AngularJS.

" только исправленный изменен " при использовании нг-Bind-HTML, в двух других примерах изменяется в "

Как я могу воспроизвести результаты ng-bind-html в моей директиве - сохраняя при этом два способа связывания ?

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

Это интересно.Кажется, что директива 'ngModel' вызывает у вас проблемы, а установка' priority' не будет исправлена. В вашем последнем примере, копируя 'ngBindHtml', если вы замените' ngModel' на другое имя (например, 'bob',' bob = "model" '), оно будет работать. http://plnkr.co/edit/eVA9lvMmwOcWKL1B2fjM?p=preview. Аналогично для вашей второй директивы, за исключением того, что требуется несколько других незначительных изменений re: parsing. – DRobinson

+1

Любопытно услышать полный ответ от кого-то, у кого больше опыта, или время, чтобы вникать в директиву 'ngModel'. Если этого не произойдет, я буду копаться в этом источнике, когда у меня будет немного больше времени :). На данный момент, как я уже упоминал, обновление для другого атрибута работает и для вашей другой директивы, также http://plnkr.co/edit/lVH1IQAhMfAot116xfiM?p=preview – DRobinson

+0

Мне нужно посмотреть, что я могу выкопать на 'ngModel' когда у меня есть шанс. Это позор, изменяющий атрибут, который не позволяет двусторонней привязке к функции еще! – Amicable

ответ

2

Оказывается, как можно было бы ожидать, служба санитарии возвращается один и тот же результат. Размещение точки останова внутри ngBindHtmlDirective. Мы можем вмешаться и посмотреть, что происходит. Мы погружаемся и исследуем значения внутри $SanitizeProvider. Значение buf, который будет возвращен обратно в ngBindHtmlDirective является:

Это в & # 34; котировки & # 34; для тестирования

Точно так же, как мы получаем для вызова $ sanitize, так в чем же разница? Реальная разница между внутреннимHTML текстовым полем и значением. Посмотреть example plunker. Вы можете видеть разницу между вызовами двух разных методов, с разными способами избежания двойной кавычки. Я не стал копать, хотя спецификацию w3 или код браузера, но я предполагаю, что назначение innerHTML выполняет дополнительную работу под капотом создания documentFragment, захватывая его textContent, а затем присваивая это значению текстового поля. Очевидно, что значение просто захватывает строку и вставляет ее как есть.


В чем проблема с вашими директивами? Я вижу, что element.html(processed) в комментарии, но раскомментирование его не влияет. Ну, правда в том, что он работает на долю секунды! Выбрав хотя бы отладчик, значение текстового поля правильно установлено, но затем цикл $ digest запускается и немедленно меняет его! Истина заключается в том, что ngModelDirective мешает, в частности, это $render function of the baseInputType. В коде используется код element.val.

Как мы можем исправить это в директивах? Требовать ngModelController и переопределить функцию $ render вместо метода element.html (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); 
}; 
Смежные вопросы