Microsoft Developer Microsoft Developer - 4 months ago 43
AngularJS Question

Create directive in typescript to show loading progress in angular

I am trying to create directive in Typescript which will keep watch on pending $resource requests. I want only one directive as an attribute which will be used with div in index.html to show loading progress. Below is my code for directive.

module app.common.directives {

interface IProgressbarScope extends ng.IScope {
value: number;
isLoading: any;
showEl: any;
}

class Progressbar implements ng.IDirective {

static $inject = ['$http'];
static instance(): ng.IDirective {
return new Progressbar;
}
//transclude = true;
restrict = 'A';
replace = true;

link = function (scope: IProgressbarScope, elements: ng.IAugmentedJQuery, attrs: ng.IAttributes, $http: ng.IHttpService) {

debugger;
scope.isLoading = function () {
return $http.pendingRequests.length > 0;
};
scope.$watch(scope.isLoading, function (v) {
debugger
if (v) {
elements.addClass("hidediv")
} else {
elements.removeClass("hidediv");
}
});
}
}

angular.module('app')
.directive('progressbar', Progressbar.instance);
}


in Index.html, it is used as below:

<div progressbar id="myProcess" name="myProcess">
// loading image
</div>


But in directive, $http is always undefined. Note that I am not using $http directly. I a using $resource service for making server side api requests.

Answer

The reason $http undefined is, you are trying to get $http dependency from link function of directive. Basically 4th parameter of link function stands for require controller.

You should Ideally get that injected dependency instance from Progressbar constructor function.

class Progressbar implements ng.IDirective {
    _http: ng.IHttpService; //defined _http variable
    static $inject = ['$http'];
    //asking for dependency here
    static instance($http: ng.IHttpService): ng.IDirective {
        this._http = $http; //get `$http` object assigned to `_http`
        return new Progressbar;
    }
    //transclude = true;
    restrict = 'A';
    replace = true;

    //removed dependency from here
    link = function (scope: IProgressbarScope, elements: ng.IAugmentedJQuery, attrs: ng.IAttributes) { 

        //use arrow function here
        scope.isLoading = ()=> {
            return this._http.pendingRequests.length > 0;
        };
        //use arrow function here
        scope.$watch(scope.isLoading, (v)=> {
           if (v) {
                elements.addClass("hidediv")
            } else {
                elements.removeClass("hidediv");
            }
        });
    }
}
Comments