3

I've got project in AngularJS and I have baseController and child controller inheriting from it.

class BaseController {
    constructor($log, $state) {
        'ngInject';

        this.$log = $log;
        this.$state = $state;
    }
}

class ChildController extends BaseController {

    constructor(myService) {
        'ngInject';

        super();
        this.myService = myService;
    }
}

My question is: Do I need to inject all parent dependency injections into child controller even when I am not using it?

Above example shows what I want to achieve, but it's not working. Anyone got idea if I can achieve it without passing BaseController services into super($scope, $state) invocation?

5
  • Why do you not use super($scope,$state) ? Commented Aug 18, 2017 at 13:38
  • I need to inject them twice. First time in child constructor and pass it to super to BaseController, which already have these injected. Seems redundant to me. For now I did super($scope, $state), but I want to know if is there a better way? doing it for 2 injections is ok, but when I have ~7 or more it is a bit of work to correct DI in parent and every child class. Commented Aug 18, 2017 at 13:42
  • Class based controllers should avoid injecting $scope. Common functions should be moved to services instead of extending controller classes. Commented Aug 18, 2017 at 14:31
  • $scope is just an example. Let's pretend instead of scope, there is my custom service (for example AuthenticationService). Commented Aug 18, 2017 at 15:37
  • The $injector Service only injects dependencies into the constructor function of the instantiated class. It does not inject into construction functions of ancestor classes. Commented Aug 18, 2017 at 16:25

1 Answer 1

5

The $injector Service only injects dependencies into the constructor function of the instantiated class. It does not inject into construction functions of ancestor classes.

To construct a controller with injectables from an ancestor class, use the $injector service and angular.extend:

class BaseController {
    constructor($log, $window) {
        'ngInject';

        this.$log = $log;
        this.$window = $window;
    }
}

class ChildController  ̶e̶x̶t̶e̶n̶d̶s̶ ̶B̶a̶s̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶ {

    constructor(myService, $injector) {
        'ngInject';
        var base = $injector.instantiate(BaseController);
        angular.extend(this, base);
        ̶s̶u̶p̶e̶r̶(̶)̶;̶
        this.myService = myService;
    }
    $onInit() {
      this.$log.info("$onInit");
      this.$log.log(this.base);
    }
}

The DEMO

class BaseController {
    constructor($log, $window) {
        'ngInject';

        this.$log = $log;
        this.$window = $window;
        this.base = "Hello from BaseController";
    }
}

class ChildController {

    constructor(myService, $injector) {
        'ngInject';
        var base = $injector.instantiate(BaseController);
        angular.extend(this, base);
        //super();
        this.myService = myService;
    }
    $onInit() {
      this.$log.info("$onInit");
      this.$log.log(this.base);
    }
}

angular.module("app",[])
.controller("child", ChildController)
.value("myService", {})
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app" ng-controller="child as vm">
    {{vm.base}}
  </body>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, works well for my case, but it looks a bit hacky (not complaining) ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.