Rohit Rane
Rohit Rane

Reputation: 2930

Dependency Injections are undefined in controller functions while using Angular1+ ES6, with controller as a class

I am using ES6 class to define my controller so this is the syntax,

export class SearchBarController {
    constructor($log) {
        'ngInject';

        $log.debug("Hello");
    }

    textTyped($log){

        $log.debug("change fired.");
    }
} 

view :

<input type="text" data-ng-model="vm.txt" data-ng-change="vm.textTyped()"/>

So "Hello" from within the constructor is getting logged fine. But, "change fired" within the typedText() function is not firing because apparently is undefined how do I make my class function textTyped() to access the $log service?

Note : If I assign $log to a class property in the constructor like,

this.logger = $log;

And then do,

this.logger.debug("Change fired.");

this works. But I am unsure if it's the right approach.

Update: Also, this approach exposes this reference to the $log service to the view bound to this controller. Is this harmful?

Is there a better solution?

Upvotes: 5

Views: 389

Answers (3)

Rohit Rane
Rohit Rane

Reputation: 2930

In case anyone's interested I found a more elegant solution to the problem using ES6 Object Destructuring :

class ABCController {
    constructor($log, $http){
        let vm = this;
        vm.DI = () => ({$log, $http});
    }

    classFn(){
        let vm = this;
        let {$log, $http} = vm.DI();
        //Now use $log and $http straightway

        $log.debug("Testing");
        $http({...}).then();
    }

    classFn2(){
        let vm = this;
        //you can also destructure only the required dependencies in this way
        let {$http} = vm.DI();
    }
}
ABCController.$inject = ['$log', '$http'];

In this way you don't need to write ugly/confusing code like vm.DI.log, etc. Also, in this way the DIs are less exposed in the view.

Upvotes: 2

MyruBapa
MyruBapa

Reputation: 148

class SearchBarController {
    constructor($scope, $log) {
        this.log = $log;

        // Scope method
        $scope.vm = this;
    }

    textTyped(){
        this.log.debug("change fired.");
    }
}

SearchBarController.$inject = ['$scope', '$log'];

Try like this

Upvotes: 2

George Kagan
George Kagan

Reputation: 6124

this.logger = $log;

As you pointed out, is the way. Since it's an object, there is no global scope.

Upvotes: 2

Related Questions