Angular $ destroy动态插入组件

时间:2016-08-11 15:01:52

标签: angularjs angular-components

我正在构建一个模式,提供一个服务来打开和关闭它。该模态有一个控制关闭按钮的小控制器,以及进入模态内容的模板的$compile

该模板是一个组件,当然,该组件有一个控制器。

隐藏模态后,如何销毁该组件?从技术上讲,当ng-if负责从DOM中删除我的模态时,它仍然会将该组件加载到其中。

以下是代码:

modal.controller.js

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) => {
      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(() => {
        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;

modal.service.js

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(() => {
      this.config.isDisplayed = false;
      this.config = {};
    }, 310);
  }

  getConfig() {
    return () => this.config;
  }
}

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

export default ModalService;

我称之为模态的BarController:

class BarController {
  constructor(modalService) {
    this.modalService = modalService;
  }

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

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

export default BarController;

1 个答案:

答案 0 :(得分:1)

啊哈!事实证明,它并不复杂。您只需要存储组件的范围,然后在模态控制器的close函数内调用$ destroy。

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

  $onInit() {
    this.childScope = null;

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

      this.$timeout(() => {
        if (this.config.template) {
          this.childScope = this.$scope.$new();

          angular
            .element('#modal-content')
            .html(this.$compile(this.config.template)(this.childScope));

          this.config.isRendered = true;
        }
      }, 0);
    }, true);
  }

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

    // this timout is used to make sure the CSS transition is executed
    // before the component is removed from the DOM.
    this.$timeout(() => {
      this.childScope.$destroy();
      angular.element('#modal-content').empty();
      this.modalService.close();
    }, 310);
  }
}

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

export default ModalController;