How do I make angular.js reevaluate / recompile inner html?

后端 未结 3 1639
慢半拍i
慢半拍i 2020-12-08 00:26

I\'m making a directive that modifies it\'s inner html. Code so far:

.directive(\'autotranslate\', function($interpolate) {
    return function(scope, elemen         


        
相关标签:
3条回答
  • 2020-12-08 01:05

    This turned out to work even better than @Reza's solution

    .directive('autotranslate', function() {
      return {
        compile: function(element, attrs) {
          var html = element.html();
          html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) {
            return '<span translate="' + text + '"></span>';
          });
          element.html(html);
        }
      };
    })
    

    Reza's code work when scope is the scope for all of it child elements. However, if there's an ng-controller or something in one of the childnodes of this directive, the scope variables aren't found. However, with this solution ^, it just works!

    0 讨论(0)
  • 2020-12-08 01:08

    Here's a more generic method I developed to solve this problem:

    angular.module('kcd.directives').directive('kcdRecompile', function($compile, $parse) {
      'use strict';
      return {
        scope: true, // required to be able to clear watchers safely
        compile: function(el) {
          var template = getElementAsHtml(el);
          return function link(scope, $el, attrs) {
            var stopWatching = scope.$parent.$watch(attrs.kcdRecompile, function(_new, _old) {
              var useBoolean = attrs.hasOwnProperty('useBoolean');
              if ((useBoolean && (!_new || _new === 'false')) || (!useBoolean && (!_new || _new === _old))) {
                return;
              }
              // reset kcdRecompile to false if we're using a boolean
              if (useBoolean) {
                $parse(attrs.kcdRecompile).assign(scope.$parent, false);
              }
    
              // recompile
              var newEl = $compile(template)(scope.$parent);
              $el.replaceWith(newEl);
    
              // Destroy old scope, reassign new scope.
              stopWatching();
              scope.$destroy();
            });
          };
        }
      };
    
      function getElementAsHtml(el) {
        return angular.element('<a></a>').append(el.clone()).html();
      }
    });
    

    You use it like so:

    HTML

    <div kcd-recompile="recompile.things" use-boolean>
      <div ng-repeat="thing in ::things">
        <img ng-src="{{::thing.getImage()}}">
        <span>{{::thing.name}}</span>
      </div>
    </div>
    

    JavaScript

    $scope.recompile = { things: false };
    $scope.$on('things.changed', function() { // or some other notification mechanism that you need to recompile...
      $scope.recompile.things = true;
    });
    

    Edit

    If you're looking at this, I would seriously recommend looking at the website's version as that is likely to be more up to date.

    0 讨论(0)
  • 2020-12-08 01:09

    You have to $compile your inner html like

    .directive('autotranslate', function($interpolate, $compile) {
        return function(scope, element, attr) {
          var html = element.html();
          debugger;
          html = html.replace(/\[\[(\w+)\]\]/g, function(_, text) {
            return '<span translate="' + text + '"></span>';
          });
          element.html(html);
          $compile(element.contents())(scope); //<---- recompilation 
        }
      })
    
    0 讨论(0)
提交回复
热议问题