Reputation: 22306
I have a promise chain that looks like this ...
this.getFile(fileId).then(updateFile).then(displayAllDoneMessage);
where getFile()
and updateFile()
each use ngResource
to construct the appropriate JSON call, and then return the $resource.$promise
.
The chain fires OK, but I'm having a problem accessing $scope
from within updateFile
So in getFile()
I have
// this works
this.status.text = "fetching file"
But in updateFile()
I have
// this fails at runtime because "this" is not $scope
this.status.text = "updating file"
What am I doing wrong, or what extra do I need to do to make $scope
available within updateFile()
?
I should possibly add that I'm using TypeScript in case that is significant.
Upvotes: 1
Views: 421
Reputation: 44916
If you are using TypeScript and you want to maintain your this
pointer, then you need to ensure you are using the lambda syntax.
Assuming you have saved off your $scope
as a private/public variable in your constructor like this:
constructor(private $scope){ /* snip */ }
Then you can simply do this to ensure you are accessing your $scope
like so:
this.getFile(fileid)
.then((result) => {
return this.$scope.updateFile(result);
})
.then((result) => {
return this.$scope.displayAllDoneMessage(result);
});
Under the hood this gets compiled down to something like the following:
//Save 'this' off to a closure
var _this = this;
_this.getFile(fileid)
.then(function(result){
return _this.$scope.updateFile(result);
})
.then(function(result){
return _this.$scope.displayAllDoneMessage(result);
});
TypeScipt uses a closure to maintain the appropriate references to this
Upvotes: 3
Reputation: 48982
When you call this.getFile
, the context is this
, in your case, I guess this
is the $scope object so this
inside getFile
is the $scope.
But updateFile
and displayAllDoneMessage
are invoked by the framework as a callback and this
no longer refers to the $scope.
Try .bind to bind the $scope as the context:
this.getFile(fileId).then(updateFile.bind(this)).then(displayAllDoneMessage.bind(this));
For older browsers, you could include this script as a polyfill (quoted from the docs):
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
Upvotes: 0