1

The Angular gets some JSON from a service as part of the route resolve.

The JSON is injected into the controller as an Angular-ish deserialized object.

The properties of the object line up with the provided TypeScript class, so vm.foo.displayName is successfully displayed on the html page for example.

But I think the methods defined in the TypeScript class are nowhere to be found, so when I try to call vm.foo.run(), the console prints the error: TypeError: Object doesn't support property or method 'run'

module app.Samples {

    export class Foo {
        public typeName: string;
        public displayName: string;

        public run(): void {
            alert("Running!");
        }
    }
}

module app.Samples {

     interface IFoobarScope {
         foo: Foo;
     }

     class FoobarController implements IFoobarScope {
         foo: Foo;

         static $inject = ['foo'];
         constructor(foo: Foo) {
             var vm = this;
             vm.foo = foo;
             vm.foo.run();
         }
     }

     angular
         .module('app.Samples')
         .controller('app.Samples.FoobarController', FoobarController);
 }
RJB
  • 2,063
  • 5
  • 29
  • 34

1 Answers1

2

Yes, as far as AngularJS is concerned, it's just passing any old object into your controller function. TypeScript provides the syntactical sugar for the Foo class within your code, but it's not going to give an object a run() method if it doesn't have one.

You could create a copy constructor for your Foo type:

constructor(foo?: Foo) {
    if(foo) {
        this.typeName = foo.typeName;
        this.displayName = foo.displayName;
    }
}

And then do this in your controller:

constructor(foo: Foo) {
    var vm = this;
    vm.foo = new Foo(foo);
    vm.foo.run();
}

Alternatively, you could skip the copy constructor approach and use angular.extend():

constructor(foo: Foo) {
    var vm = this;
    vm.foo = new Foo();
    angular.extend(vm.foo, foo);
    vm.foo.run();
}
JLRishe
  • 99,490
  • 19
  • 131
  • 169
  • That's what I suspected, but something about your solution / the way you said it made a lightbulb go off. It's not necessary to manually reflect the injected object unto the constructed object. I'll mark as the answer if you can edit from `vm.foo = new Foo(foo);` to `vm.foo = new Foo(); angular.extend(vm.foo, foo);` :-) – RJB Jan 27 '15 at 22:38
  • Good synopsis of angular.extend and/or angular.copy: http://stackoverflow.com/questions/16797659/jquery-extend-vs-angular-extend – RJB Jan 27 '15 at 22:39
  • 1
    @RJB There may be some merit in the approach I originally posted, so I've edited my answer to additionally include your suggestion. – JLRishe Jan 27 '15 at 22:41