1

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.

2 Answers 2

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");
            }
        });
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. It worked. Can't I use elements.show() property instead of adding class? I am getting "angular.js:13550 TypeError: elements.show is not a function" error if I use elements.show()
@MicrosoftDeveloper check updated answer, you should use Arrow function instead of plain javascript function
0

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

Comments

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.