<!DOCTYPE html>
<html>

  <head>
    <script data-require="angularjs@1.6.2" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.js"></script>
    <!-- <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script> -->
    <link rel="stylesheet" href="style.css" />
    <script src="script.js"></script>
  </head>

  <body ng-app="iframeDirective">
    <div ng-controller="TestController">
      <textarea ng-model="template"></textarea>
      <br />
      <textarea ng-model="injectableContent1"></textarea>
      <br />
      <textarea ng-model="injectableContent2"></textarea>
      <br />
      <my-iframe iframe-template="template" iframe-context="{injectableContent1: injectableContent1, injectableContent2: injectableContent2}"></my-iframe>
    </div>
  </body>

</html>
'use strict';

(function() {
angular.module('iframeDirective', [])
.controller('TestController', ['$rootScope', '$scope', 
function($rootScope, $scope) {
  $scope.template = 
`<p>some text in the template</p>
<my-dynamic-html contents="injectableContent1"></my-dynamic-html>
<my-dynamic-html contents="injectableContent2"></my-dynamic-html>`;
  $scope.injectableContent1 = 
`<h1>First set of injectable content</h1>
<p>Lorem ipsum</p>`;
  $scope.injectableContent2 = 
`<h1>Second set of injectable content</h1>
<p>Lorem ipsum</p>`;
}
])
.directive('myIframe', ['$compile', 
function($compile) {
  return {
    restrict: 'E',
    template: `
      <iframe></iframe>
    `,
    scope: {
      iframeTemplate: '=',
      iframeContext: '='
    },
    link: function($scope, $element, $attrs) {
      
      let setScope = () => {
        angular.forEach($scope.iframeContext, (value, key) => {
          $scope[key] = value;
        });
        setContextWatchers();
      };
      
      let render = () => {
        $compile($element
          .find('iframe').contents()
          .find('body').html($scope.iframeTemplate)
          .contents()
        )($scope);
      };
      
      let setContextWatchers = () => {
        angular.forEach($scope.iframeContext, (value, key) => {
          $scope.$watch(
            ($scope) => {
              return $scope.iframeContext[key];
            },
            () => {
              $scope[key] = $scope.iframeContext[key];
            });
        });  
      };
      
      $scope.$watch('iframeTemplate', () => {
        setScope();
        render('template');
      });
    }
  }
}
])
.directive('myDynamicHtml', ['$compile', 
function($compile) {
  return {
    restrict: 'E',
    scope: {
      contents: '='
    },
    link: function($scope, $element, $attrs) {
      let element = $element;
      $scope.$watch('contents', () => {
        let newElement = $compile($scope.contents)($scope);
        element.replaceWith(newElement);
        element = newElement;
      });
    }
  };
}
])
})();
/* Styles go here */

# Angular directive to load HTML supporting dynamic content, into an iFrame