0

I have been learning Angular and everything's been going smoothly. I have decided to try and incorporate TypeScript into this and wrote a small test controller in an already existing Angular/WebApi project I have been working on.

The controller "works" and initializes just fine, however, my $scope properties are not being updated when set to an HTTP promise. I have attached a "working" example of my issue using the TypeScript generated JS file. When debugging, I can see the then get triggered on the promise and the data I expected does return, but the page displays {}

Here is my actual TypeScript file.

/// <reference path="../../tds/angularjs/angular.d.ts" />
module RecordEditor {
    export interface Scope extends ng.IScope{
        tableId: any;
    }

    export class Controller {
        $scope: Scope;
        api : any;
        constructor($scope: Scope, myApi: any) {
            this.api = myApi;
            this.$scope = $scope;
            this.$scope.tableId = this.api.getTestResponse();
        }
    }
}

var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);

That controller is the only thing I have actually written in TypeScript. All the other controllers are in JavaScript and the same api I built returns responses just fine with those.

Below is the actual runnable snippet code with the JavaScript version of my Controller.

(function() {

  var app = angular.module('myApp', []);

}());

(function() {
  var myApi = function($http) {

    var getTestResponse = function() {
      // Hope it is okay to use SE API to test this question. Sorry if not.
      return $http.get("https://api.stackexchange.com/2.2/sites")
        .then(function(response) {
          return "Hello!";
        });
    };

    return {
      getTestResponse: getTestResponse,
    };

  };

  var module = angular.module("myApp");
  module.service("myApi", ['$http', myApi]);
}());

var RecordEditor;
(function(RecordEditor) {
  var Controller = (function() {
    function Controller($scope, myApi) {
      var _this = this;
      this.api = myApi;
      this.$scope = $scope;
      this.$scope.response = this.api.getTestResponse();

      this.$scope.ctorTest = 42;
    }
    return Controller;
  })();
  RecordEditor.Controller = Controller;
})(RecordEditor || (RecordEditor = {}));

var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="RecordEditor.Controller">
  <div >
    Scope property set in constructor: {{ctorTest}}
  </div>
  
  <div >
    Scope response value: {{response}}
  </div>

  <div >
    Scope response should have been "Hello!"
  </div>
</div>

Can anyone actually tell me what I am doing wrong? Everything looks fine to me.

8
  • Seems like the stackexchange call isnt working. Check this JSFiddle for the one that is working. jsfiddle.net/HB7LU/7382 Commented Oct 16, 2014 at 17:51
  • @KrishnaTejaVeeramachaneni That's the odd thing though. No errors report in the console when using the URL and I get no errors when calling my own service locally, but the result is exactly the same ({} on page instead of Hello!). And that's calling a method on the api that the other controllers can call just fine. I see your example has it working though. I am very lost right now. Commented Oct 16, 2014 at 17:54
  • Not sure why you were not seeing error in console but I was able to see 404 errors in chrome console. Commented Oct 16, 2014 at 18:02
  • Whomever had the answer for calling getTestResponse().then(...) please undelete your answer. It was correct. Commented Oct 16, 2014 at 18:10
  • @KrishnaTejaVeeramachaneni I am not getting 404s calling that URL. Commented Oct 16, 2014 at 18:12

2 Answers 2

1
var getTestResponse = function() {
  return $http.get("https://api.stackexchange.com/2.2/sites")
    .then(function(response) {
      return "Hello!"; // <-- does not do what you think it does
    });
};

/** elsewhere **/
this.$scope.response = this.api.getTestResponse();

The inner return statement here does not return a value from getTestResponse. Instead, it returns a value from the Promise which is basically discarded. getTestResponse returns immediately with a Promise object that is of no particular use for binding to the scope.

Fixed version of the JS:

(function() {

  var app = angular.module('myApp', []);

}());

(function() {
  var myApi = function($http) {

    var getTestResponse = function() {
      // Hope it is okay to use SE API to test this question. Sorry if not.
      return $http.get("https://api.stackexchange.com/2.2/sites")
        .then(function(response) {
          return "Hello!";
        });
    };

    return {
      getTestResponse: getTestResponse,
    };

  };

  var module = angular.module("myApp");
  module.service("myApi", ['$http', myApi]);
}());

var RecordEditor;
(function(RecordEditor) {
  var Controller = (function() {
    function Controller($scope, myApi) {
      var _this = this;
      this.api = myApi;
      this.$scope = $scope;
      /** FIXED **/
      this.api.getTestResponse().then(function(v) { _this.$scope.response = v; });

      this.$scope.ctorTest = 42;
    }
    return Controller;
  })();
  RecordEditor.Controller = Controller;
})(RecordEditor || (RecordEditor = {}));

var app = angular.module("myApp");
app.controller("RecordEditor.Controller", ['$scope', 'myApi', RecordEditor.Controller]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<div ng-app="myApp" ng-controller="RecordEditor.Controller">
  <div >
    Scope property set in constructor: {{ctorTest}}
  </div>
  
  <div >
    Scope response value: {{response}}
  </div>

  <div >
    Scope response should have been "Hello!"
  </div>
</div>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. I used the one spot it was wrong in my base as a template for setting up the TypeScript class. Everywhere else I was using then. D'OH! The TypeScript fix was this this.api.getTestResponse().then((v: any): void => this.$scope.tableId = v);
1

Ok here's the issue. You are trying to set your response to the actual callback function. Instead, you have to set the response property inside callback using the response you got from the http call.

Here is the api function

 var getTestResponse = function() {         
      return $http.get("http://vimeo.com/api/oembed.json?url=http%3A//vimeo.com/76979871");            
    };

Here is your controller code where you have to set your response property to bind to UI.

 _this.api.getTestResponse().success(function(resp) { 
      _this.$scope.response = resp.height; //I just used height property from response as example
  });

Here is the jsfiddle

http://jsfiddle.net/HB7LU/7386/

Make sure you first get your stackexachange call working. I used vimeo call as example. Let me know if you have any questions.

So, in your TypeScript code, you have to change

this.$scope.tableId = this.api.getTestResponse();

to

this.api.getTestResponse().then((resp) =>
{
    this.$scope.tableId = resp;
});

And make your API just return a promise.

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.