最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS, $http.get() and "controller as" - Stack Overflow

programmeradmin6浏览0评论

I'm pretty new to the whole AngularJS world and how it works, however I am struggling to get it working as expected. I know that its something to do with the way I am using $http.get() and trying to assign the variables back to my controller, but I just can't figure it out.

Using $scope instead of this I can get it working, however if possible, I'd prefer to be using this so I can use "controller as"

Code:

app.controller('ctrlSuppliers', function($http){

    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  this.supplierList = response.records;})
            .error(function() { this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}];});
});

From this example, I cannot then access any results from the $http.get request from within the supplierList within the HTML page (i.e. {{ supplier.supplierList[0].supplier_name }} doesnt display any results)

I know that if I change the controller to $scope I can get access to that data (although not using the same format as above), and I also know the data is being populated by using console.log(this.supplierList) inside the .success call.

I also know that the reason its not working is because the context of this changes from within the controller to within the $http.get call.

So my question is this: How do you get access to the results from a $http.xxx call using this instead of scope? I have read a few different sources on it, but most talk about using $scope and promises. I've not found any that cover using this (or declaring it with var supplier = this). Any help would be much appreciated.

Thanks,

I'm pretty new to the whole AngularJS world and how it works, however I am struggling to get it working as expected. I know that its something to do with the way I am using $http.get() and trying to assign the variables back to my controller, but I just can't figure it out.

Using $scope instead of this I can get it working, however if possible, I'd prefer to be using this so I can use "controller as"

Code:

app.controller('ctrlSuppliers', function($http){

    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  this.supplierList = response.records;})
            .error(function() { this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}];});
});

From this example, I cannot then access any results from the $http.get request from within the supplierList within the HTML page (i.e. {{ supplier.supplierList[0].supplier_name }} doesnt display any results)

I know that if I change the controller to $scope I can get access to that data (although not using the same format as above), and I also know the data is being populated by using console.log(this.supplierList) inside the .success call.

I also know that the reason its not working is because the context of this changes from within the controller to within the $http.get call.

So my question is this: How do you get access to the results from a $http.xxx call using this instead of scope? I have read a few different sources on it, but most talk about using $scope and promises. I've not found any that cover using this (or declaring it with var supplier = this). Any help would be much appreciated.

Thanks,

Share Improve this question edited May 14, 2015 at 16:00 Doug asked May 14, 2015 at 15:54 DougDoug 54710 silver badges24 bronze badges 2
  • Just a heads-up that $http calls usually don't belong in your controllers! Extract them to a service instead for reusability, stability, and non-gratuitous dependency injection. – Hypaethral Commented May 14, 2015 at 16:19
  • @GrumbleSnatch Thanks for that. As I said, I've only just started looking at Angular and haven't had time to look through all the features and functions yet, however knowing about it now will likely save me a lot of time down the track when I eventually discovered them – Doug Commented May 14, 2015 at 18:56
Add a ment  | 

5 Answers 5

Reset to default 9

Always store a variable reference to this so that you don't have context issues, then use that variable instead of this throughout controller

app.controller('ctrlSuppliers', function($http){
    var vm = this;
    // now can forget using "this" and use variable instead
    vm.supplierList = {};

    $http.get("http://some_url_here") .success(function(response) {
         // no context issues since "vm" is in scope  
         vm.supplierList = response.records;
    });               
});

For $http you have the option of storing your own objects in the configObject which is the optional second argument to $http.get(). This object is then made available to you as it's a property of response.

This technique is especially useful if you're calling $http.get() multiple times in a loop.

The this variable is tricky in JavaScript. When callback function is executed you won't know what the this is referencing. Unless it's documented somewhere.

You have to use the .bind(this) to attach your own this value to be used in the function.

app.controller('ctrlSuppliers', function($http){
    this.supplierList = {};
    $http.get("http://some_url_here")
            .success(function(response) {
                 this.supplierList = response.records;
            }.bind(this))
            .error(function() { 
                 this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}];
            }.bind(this));
});

See bind manual:

https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

With arrow functions available in ecmascript 6 the problem with this is taken care of and you have less to type. Your example would look like this :

app.controller('ctrlSuppliers', function($http){
    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(response => { this.supplierList = response.records; })
            .error(() => { this.supplierList = [{supplier_id: 0, supplier_name: 'Error Getting  Details'}]; });
});

the result is equivalent to storing this to a variable but more concise.

I think charlietfl's answer is the correct one, but think a slightly expanded explanation might be helpful.

"this" in javascript refers the the context of the current function call. If you look at your code, you'll see that this is being used in two functions -

app.controller('ctrlSuppliers', function($http){

    //first use of this - used in the context of the controller function
    //In this case, this = the controller
    this.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  
                //second use of this - used in the context of the http success function callback
                //this will likely not be the controller.  It's value depends on how the caller (the $http framework) invoked the method.
                this.supplierList = response.records;
             })
             ....

Since they are two different functions, they may have pletely different contexts, so "this" will refer to different objects (as you are experiencing).

The standard way of dealing with this is to save the call context of the first function for use in the others. @charlietfl's answer is a good way to acplish this. I've added his code for reference.

app.controller('ctrlSuppliers', function($http){
    var vm = this;
    vm.supplierList = {};

    $http.get("http://some_url_here")
            .success(function(response) {  vm.supplierList = response.records;})
});
发布评论

评论列表(0)

  1. 暂无评论