Junlong Wang
Junlong Wang

Reputation: 456

Controller inheritance in Typescript with minification causing Error: $injector:unpr Unknown Provider

UPDATE 2019/07/16

My issue is actually caused by the inappropriate use of $inject. I used it as private $inject in api-service.ts but it should be public static $inject = [...]. When uglifying, it relies on the explicit injection but private $inject made it implicit


I have a very much the same issue with this post. Instead of the tProvider unknown, my error message has the specific provider name but look like

Unknown provider: eProvider <- e <- api-service <- baseDI-service

where api-service and baseDI-service are named and registered services for the same module.

My module looks like as below:

module
--api-service
--other-services
--baseDI-service
--componentA
----controllerA extends BaseController
--componentB
----controllerB extends BaseController

I import api-service and other services in baseDI-service which I used as a service container because I don't want to pass a lot parameters in super() of componentA, for example.

So in componentA it looks like:

...
class ComponentAController extends BaseController {
    public static $inject = ['baseDI-service', ...];

    constructor(baseDIService: BaseDIService) {
        ...
        super(baseDIService); 
        ...
    }
}

BaseDIService.ts:

export default class BaseControllerDIService {
    public static $inject = ['api-service', '$http', ...];
    constructor(
        private apiSvc: ApiService,
        private $http: ng.IHttpService,
        ...
    ) {}

    public getBaseClassDependencies() {
        return{
            apiService: this.apiSvc,
            $http : this.$http
            ... : ...
        };
    }
}

BaseController.ts

export default class BaseController implements ng.IComponentController {    
    apiService: ApiService;
    $http: ng.IHttpService;

    constructor(
        baseDIService: BaseDIService
    ) {
        const services = baseDIService.getBaseClassDependencies();
        this.$http = services.$http;        
        this.apiSvc = services.apiService;
        ...
        this.otherService = services.otherServices;
        ...
    }

After Grunt Uglify minification, the error was like Unknown provider: serviceAProvider <- serviceA. Without minification, everything alright.

Prior to this way, I also tried using $injector the same way as baseDI-service in controllerA to pass it to super(), and in BaseController I use $injector.get('api-service'), I got the same issue with minification only.

Could anyone tell why both way I tried failed in Uglify minified mode, and how can sort it out? I do need minification by the way.

Also, is it a good practice using controller inheritance for AngularJS?

Upvotes: 1

Views: 193

Answers (1)

georgeawg
georgeawg

Reputation: 48968

To help you find this kind of problem before you uglify, use Strict Dependency Injection.

From the Docs:

Using Strict Dependency Injection

You can add an ng-strict-di directive on the same element as ng-app to opt into strict DI mode:

<!doctype html>
<html ng-app="myApp" ng-strict-di>
<body>
  I can add: {{ 1 + 2 }}.
  <script src="angular.js"></script>
</body>
</html>

Strict mode throws an error whenever a service tries to use implicit annotations.

For more information, see

Upvotes: 2

Related Questions