Using AngularJS 1.6.1 (ES6/Babel)... controller invokes a service method which uses $http.post() so I thought it would automatically run the digest. Had to add $timeout to force it (prefer to avoid $scope.$apply as this is an Angular component and will be upgrading to AngularJS 2 soon).
Is there a better approach than what I've done? Should then() off of what was originally an $http.post have run the digest cycle? If I don't include $timeout, nothing gets updated in the view.
Place Order button submits a form with its ngClick as $ctrl.placeOrder(checkout):
placeOrder(form) {
if(form.$valid) {
return this.Cart.placeOrder()
.then(saleResponse => {
// Page has {{ $ctrl.pageName }} but won't update without digest cycle
this.pageName = 'Order Confirmation'; // displays confirmation
form.$setPristine(); // treat the fields as untouched
form.$submitted = false; // reset submitted state
// Force a digest to run. Why is this needed?
this.$timeout(() => this.pageName);
})
.catch(saleResponse => {
form.$submitted = false;
this.errorMessage = saleResponse.message;
if(this.errorMessage.includes('card')) this.focusOnCardNumber();
});
}
}
Here's Cart.placeOrder():
placeOrder() {
// braintreeHostedFieldsTokenize() is a wrapper to return new Promise for their callback-based API
return this.braintreeHostedFieldsTokenize(this.hostedFieldsInstance)
.then(this.postOrderInformation.bind(this));
}
and Cart.postOrderInformation()
postOrderInformation(payload) {
const orderInformation = {
nonceFromClient: payload.nonce,
purchaser: this.purchaser,
recipient: this.recipient,
cartItems: this.cartItems
};
return this.$http
.post('/api/order', orderInformation)
.then(orderResponse => {
this.confirmation = orderResponse.data;
if(!orderResponse.data.success) throw orderResponse.data;
return this.confirmation;
});
}
Any thoughts about where I might have gone wrong necessitating the use of $timeout? My assumption was that $http.post's then() would run the digest cycle on its own since it's AngularJS. Thanks in advance.
My thought is that the
.then
method ofCart.placeOrder()
is being performed on a promise library/queue that is external to the Angular $q Service library/queue. Try moving it to the $q Service with$q.when
:The promise returned by
braintreeHostedFieldsTokenize()
is not a $q Service promise and thus not integrated with the Angular digest cycle.-- AngularJS $q Service API Reference - $q.when