【问题标题】:How do you use angularjs upgraded components within an ngx-bootstrap Modal?您如何在 ngx-bootstrap 模态中使用 angularjs 升级组件?
【发布时间】:2020-12-10 20:32:29
【问题描述】:

我有一个使用 Valor Software 的 ngx-bootstrap (5.3.2) 模式的混合 Angular 应用程序(Angular 8.2.14 和 angularjs 1.8.0)。我仍然有几个组件是 angularjs 并且足够复杂,我不能只是快速升级它们。

我已正确引导我的应用程序,以便通常升级和降级的组件按预期工作。有一种情况不会发生这种情况,我认为这是因为 ngx-bootstrap 的 BsModalService 创建组件的方式。

给定一个具有如下定义的 Angular 组件 TestModal:

@Component({ template: `
  <ng1-component [html]="ng1HtmlContent"></ng1-component>
` })
export class TestModal {
  public ng1HtmlContent: string;
}

还有一个像这样的 angularjs 组件:

angular.
  module('common').
  directive('ng1Componnent', ng1Component);

ng1Component.$inject = ['$compile'];
function ng1Component ($compile) {
  return {
    restrict: 'E',
    scope: {
      html: '<'
    },
    template: '<div></div>',
    link: function ng1Component (scope, elem) {
      let childScope = null;

      scope.$watch('html', (html) => { 
        if (childScope) {
          childScope.$destroy();
        }

        childScope = scope.$new();
        // There is a lot more here I am just not including.

      });
  }
}

模态显示的代码类似于:

constructor(private readonly bsModalService: BsModalService) {}

public showTest(initialState: Partial<TestModal>): void {
  this.bsModalService.show(TestModal, { initialState });
}

如果我将我的 ng1Component 直接放入 DOM 而不是模态框内,则组件会按您的预期呈现。但是,如果在模态中使用 ng1Component 我会收到此错误:

ERROR NullInjectorError: StaticInjectorError(AppModule)[$scope]: 
  StaticInjectorError(Platform: core)[$scope]: 
    NullInjectorError: No provider for $scope!

显然,模态代码没有被插入到 DOM 中正确引导的 ng1Injector 可以提供范围的地方。

还有其他人解决过这个问题吗?如果是这样,你是怎么做的?

【问题讨论】:

    标签: angularjs angular angular-upgrade ngx-bootstrap-modal


    【解决方案1】:

    看起来问题是UpgradeComponent 注入器在尝试升级组件时无法获取父作用域。深入UpgradeComponent 代码,我们会遇到这个代码:

    function UpgradeComponent(name, elementRef, injector) {
      // ... code removed for brevity
    
      // We ask for the AngularJS scope from the Angular injector, since
      // we will put the new component scope onto the new injector for each component
      var $parentScope = injector.get($SCOPE);
      this.$componentScope = $parentScope.$new(!!this.directive.scope);
    
      // ... code removed for brevity
    }
    

    当我在执行时检查 $parentScope 时,我看到了undefined。有趣的是注入器很好,所以升级模块确实有注入器,问题只是它找不到父作用域。

    我的 angularjs 组件都有isolateScopes,所以我需要一个$scope,但我不需要父母$scope。所以我的解决方案是将$scope 作为$rootScope 的新实例提供给注入器。这看起来像:

    @Component({ template: `
      <ng1-component [html]="ng1HtmlContent"></ng1-component>
    `,
      providers: [
        {
          deps: ['$injector'],
          provide: '$scope',
          useFactory: ($injector: Injector) => $injector.get('$rootScope').$new()
        }
      ]})
    export class TestModal {
      public ng1HtmlContent: string;
    }
    

    我不确定这是否是最好的解决方案,但这是我能想到的最简单的解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-04-04
      • 1970-01-01
      • 2019-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-11
      • 1970-01-01
      相关资源
      最近更新 更多