0

i want to convert existing directive in javascript to typescript. How do i convert below function

    $scope.loadData = function () {
        $scope.tableParams = $cspagination.initPromise(getPagedData);
    };

So I am trying to write it as

  class controller {
    this $scope.loadData = (): void {
      .....
      .....
    };
  }

but it is giving error that this is not available on class level. then i tried

  class controller {
    public $scope.loadData = (): void {
      .....
      .....
    };
  }

but this also does not work. its obvious that I cannot define a new public property on $scope, but then atleast I should be able to assign value to it.

so how do I dynamically add functions on $scope?? The workaround I could think of is creating a function extendScope and then

   class controller {
    public loadData = (): void => {
      .....
      .....
    };

    private extendScope = (): void =>{
       this.$scope.loadData = this.loaddata;
    }

  constructor(){
      this.extendScope();
  }

  }

but then this feels like a hack.. are there any cleaner ways of doing this?

harishr
  • 17,807
  • 9
  • 78
  • 125
  • This is no hack. Normally in javascript you do it on 'constructor'-time, in typescript in the `constructor` as well, though you should not make the `loadData` method public, if you only want to assign it to the `$scope` – devqon Aug 10 '16 at 08:36
  • `extendScope` is redundant, it is as simple as `angular.extend(this.$scope, this)` or `Object.assign(this.$scope, this)` (considering that all `this` methods are arrows and keep their contexts). It should feel like a hack because it is a hack, the proper way to do this is `controllerAs`. – Estus Flask Aug 10 '16 at 13:29

2 Answers2

1

The way I go - is to create custom scope definition (i.e. inteface), e.g.:

export interface IMyScope  extends ng.IScope
{
    loadData: () => void;
    otherFunction: function;
    ...
    Ctrl: MyCtrl;
}

and Controller constructor now requires that interface

export class MyCtrl
{
    static $inject = ["$scope", ...];
    constructor(protected $scope: IMyScope  ,
        ...)
    {
       this.$scope.Ctrl = this; // we can use "controllerAs" as well
        // and here we can add these functions
       this.$scope.loadData = this.loadData;
       this.$scope.otherFunction = function() {};
       ...
    }

    public loadData = (): void => {
       //.....
    }

See more here:

Community
  • 1
  • 1
Radim Köhler
  • 122,561
  • 47
  • 239
  • 335
  • ok, I used example with not function properties- defined on `IMyScope`.. now I adjusted that example.. hope it helps a bit. But I would not use the `$scope.loadData` but `$scope.Ctrl.loadData...`. so in template `ng-click="Ctrl.loadData()"` – Radim Köhler Aug 10 '16 at 08:54
  • thats the solution I had thought of, but felt like a hack :( – harishr Aug 10 '16 at 11:34
  • what is *"the native solution"* in this case - `controllerAs` and inside of the template referencing `Ctrl.methods()`... with combination `bindToController` you have almost ng2 behavior... anyhow, good luck with Typescript and Angular ;) – Radim Köhler Aug 10 '16 at 12:01
1

I don't see anything wrong with this, only that your loadData method shouldn't be public in this case. What I would do though is use the 'controller-as' method:

class controller {
    static ID = "myController";

    // defining methods like this will make them immediately available on 
    // the controller with the 'controller as' method
    public loadData = (): void => {
        //.....
    }

    constructor(){
    }

}

And in your html:

<div ng-controller="myController as $my">
    <button ng-click="$my.loadData()">Load!</button>
</div>
devqon
  • 13,818
  • 2
  • 30
  • 45
  • I am aware that controller-as will solve this problem, but then I will have to touch the html pages and that would increase the scope ,I dont want to touch html as of now... – harishr Aug 10 '16 at 08:50