I ran into a problem (which I think I understand), but I'm not clear about what the solution could be.
In a nutshell, I have a BackendService
that wraps some non-Angular object model (in my case, SharePoint, but that is beside the point). I created this BackendService
so that it could return Angular-compatible entities (items
), so that I could do something like the following:
angular.module("app", [])
.factory("BackendService", function(){
return new BackendService();
})
.controller("MainCtrl", function($scope, BackendService){
BackendService.GetItems()
.then(function(items){
$scope.Items = items;
$scope.$apply();
});
});
So far so good.
Except, I wanted each item
to be a self-sufficient and ViewModel-y such that it could be used directly in the View. In other words, I wanted to do the following (notice the button's ng-show
and ng-click
):
<div ng-controller="MainCtrl">
<div ng-repeat="item in Items">
<input ng-model="item.fieldA" type="text"/>
<input ng-model="item.fieldB" type="text"/>
<button ng-show="item.IsDirty()" ng-click="item.Save()">Save</button>
</div>
</div>
The button shows immediately when there is any change (which sets the dirty flag), but when item.Save()
- an async function - is called where the dirty flag is unset, the change is not visible in the DOM.
So the problem is: the button doesn't hide when item.IsDirty() === false
.
My understanding is that item.Save()
being an async function that uses the object model which uses Ajax under the covers (which doesn't use $http since it's not aware of Angular) thus bypasses the digest loop. Because of this, the change in item.IsDirty()
is never reflected in the DOM.
Questions:
- Is my understanding of the issue correct?
- Have I offended an Angular best practice with this approach?
- Must I now do something
like
<button ng-click="SaveItem(item)">
and call$scope.$apply
within it?
Edit (in response to an answer by Gordon):
- Is it a good idea to pass $scope or use $rootScope deep in the service, or should the service be Angular-agnostic? If not, what would be preferable?
Thanks!