Create directive in typescript to show loading pro

2019-07-28 06:55发布

问题:

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.

回答1:

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");
            }
        });
    }
}


回答2:

define $scope.isLoading inside directiveController and make $http call from service layer.

basic controller.ts

export class sampleController {

    // inject service here  
    constructor() {

    }

    public isLoading() {
        callServiceFunction();
    }
}

sampleController.$inject['service'];

Import this controller inside custom directive.

SampleService.ts

export class sampleService {
  constructor() {


  }

}
sampleService.$inject = ['$http'];

Register this service inside app module.

For more info refer sample Importing and exporting example and large scale app architecture