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
5 Answers
Reset to default 9Always 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;})
});