1

I have a very large hybrid Angular app; the original app is angularjs 1.6.8 while the rest is Angular 7.2.15. We are working to convert the entire app to Angular, but it is slow going. Our app also relies on angular-ui-bootstrap (2.5.0) / ngx-bootstrap (3.1.3).

Each of our significant views are lazy loaded with the exception of the landing page. I am currently attempting to convert one of those views.

Our App module imports ModalModule.forRoot(). This works well until I try to access it in a downgraded service. For example, I have a route named "Account" with a service name AccountModalService with this downgrade created:

import angular from 'angular';
import { downgradeInjectable } from '@angular/upgrade/static';
import { AccountModalService as service } from './accountModal.service';

angular.module('account').factory('AccountModalService', downgradeInjectable(service));

Now from my angularjs AccountPage I should be able to open a modal like so

const accountPage = {
  controller: AccountPageCtrl,
  template: `<div><button ng-click="test()">Test</button></div>`
};

AccountPageCtrl.$inject = [
  'AccountModalService'
];
function AccountPageCtrl(AccountModalService) {
  this.test = function test() {
    AccountModalService.openTestModal(); // this would open my test modal
  };
}

angular.
  module('account').
  component('accountPage', accountPage);

I know the modal works when the openTestModal method is called from an Angular Component, but when I attempt to launch it from an angularjs component. I get the error

angular.js:14800 Error: StaticInjectorError(AppModule)[AccountModalService]: 
  StaticInjectorError(Platform: core)[AccountModalService]: 
    NullInjectorError: No provider for AccountModalService!

If I change AccountModalService to exist on the root injector, like so @Injectable({ provideIn: 'root' }), I get an error indicating that the injector can not find the component that the modal is intended to display:

angular.js:14800 Error: No component factory found for TestModalComponent. Did you add it to @NgModule.entryComponents?
    at noComponentFactoryError (core.js:9877)
    ...

The TestModalComponent is an entryComponent of the lazy loaded AccountModule and that module imports my eagerly loaded common module. But sure enough, TestModalComponent is not an entryComponent of the AppModule.

If I move my test modal component and this service into the eager loaded code, it will properly open the modal. However, this is just the first step in making the eager loaded module a monolith. It is not a pattern I want to continue as it makes lazy loaded routes worthless.

Is there any way to downgrade an angular service that uses the ngx-bootstrap modal BsModalService to show a modal from angularjs code in an lazy loaded route? Has anyone successfully done something similar who is willing to share how?

nephiw
  • 1,964
  • 18
  • 38
  • Did you ever figure this out? I have a similar situation where I want to move a downgraded component/service to a lazy loaded module and it stops working with the same errors you have listed. – Joe May 28 '20 at 23:49
  • The short answer is no - I ended up just using my original modal, but then upgrading all of the content of the modal to the Angular until both the component launching the modal, and the content of the modal were Angular 9. So basically, I kicked it down the road. – nephiw May 29 '20 at 16:09

0 Answers0