Models directly $ looked and call View using Angular - a good idea?

I ran into a problem (which I think I understand), but I don't understand what the solution is.

In a nutshell, I have BackendService

one that wraps some non-Angular object model (in my case SharePoint, but that's not the point). I created this BackendService

one so it can return Angular-Component Entities ( items

) so that I can 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.

Also, I wanted each to item

be self-contained and the ViewModel-y in a way that could be used directly in the View. In other words, I wanted to do the following (notice the ng-show

and button 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 is displayed immediately when there is any change (which sets the dirty flag), but when item.Save()

- the async function - is called where the dirty flag is disabled, that change is not visible in the DOM.

So the problem is : the button is not hiding when item.IsDirty() === false

.

My understanding is that there item.Save()

is an async function that uses an object model that uses Ajax under the covers (which doesn't use $ http since it doesn't know about Angular), thus bypassing the digest loop. Because of this, a change in c is item.IsDirty()

never reflected in the DOM.

Questions:

  • How do I understand the question correctly?
  • Have I insulted Angular best practice with this approach?
  • Should I do something now? how to <button ng-click="SaveItem(item)">

    call $scope.$apply

    inside it?

Edit (in response to Gordon's answer):

  1. Is it a good idea to pass the $ scope or use the $ rootScope deep into the services, or if the service is going to be Angular-significant? If not, which would be preferable?

Thank!

+3


source to share


1 answer


The problem is that your scope.items array is not tied to any of your service data. I would solve this problem by having an object property on the ain object in your service that is bound to the object property.

BackendService.loadData()
 .then(function() {
    $scope.data = BackendService.data;
 });
// data is an object with a property items

      

Then, as soon as there are changes to your service data, update the array of local elements and they will be tracked using angular data binding.



And I finally understood. I was able to get it around it using emit to run the app: http://plnkr.co/edit/F8rLK2?p=preview

See this Q&A for deets: angularjs ng-show with expression promise

+1


source







All Articles