AngularJS $destroy dynamically inserted component
<p>I am building a modal that provides a service to toggle it on and off. That modal has a small controller which controls the close button, and the <code>$compile</code> of the template that goes into the content of the modal.</p>

<p>That template is a component, and of course, that component has a controller.</p>

<p>How do I destroy that component, after hiding the modal? Technically, when ng-if takes care of removing my modal from the DOM, it still has that component loaded into it.</p>

<p>Here is the code:</p>

<p><strong>modal.controller.js</strong></p>

<pre><code>class ModalController {
  constructor($scope, modalService, $compile, $timeout) {
    this.$scope = $scope;
    this.modalService = modalService;
    this.$compile = $compile;
    this.$timeout = $timeout;
  }

  $onInit() {
    this.$scope.$watch(this.modalService.getConfig(), (newVal) =&gt; {
      this.config = newVal.isDisplayed
        ? angular.extend(this.config, newVal)
        : {};

      // I wait for ng-if to put the modal into the DOM then I 
      // compile the component.
      this.$timeout(() =&gt; {
        if (this.config.template) {
          const component = this.$compile(this.config.template)(this.$scope);
          angular.element('#modal-content').html(component);
          this.config.isRendered = true;
        }
      }, 0);
    }, true);
  }

  close() {
    this.modalService.close();
  }
}

ModalController.$inject = [
  '$scope',
  'modalService',
  '$compile',
  '$timeout',
];

export default ModalController;
</code></pre>

<p><strong>modal.service.js</strong></p>

<pre><code>class ModalService {
  constructor($timeout) {
    this.config = {};
    this.$timeout = $timeout;
  }

  open(newConfig) {
    this.config = newConfig;
    this.config.isDisplayed = true;
  }

  close() {
    this.config.template = null;
    this.config.isRendered = false;

    // the reason there is timeout here is to run my CSS animation
    // before ng-if removes the modal from the DOM.
    this.$timeout(() =&gt; {
      this.config.isDisplayed = false;
      this.config = {};
    }, 310);
  }

  getConfig() {
    return () =&gt; this.config;
  }
}

ModalService.$inject = [
  '$timeout',
];

export default ModalService;
</code></pre>

<p><strong>BarController where I call the modal:</strong></p>

<pre><code>class BarController {
  constructor(modalService) {
    this.modalService = modalService;
  }

  openModal() {
    this.modalService.open({
      title: 'Add a document',
      template: '&lt;foo-component&gt;&lt;/foo-component&gt;',
    });
  }
}

BarController.$inject = [
  'modalService',
];

export default BarController;
</code></pre>