vipanth vipanth - 6 months ago 19
Ajax Question

bind controllers to service with ajax promise

I'm new to angularjs. In my webapp I'm trying to work with user contacts as follows.

SERVICE

app.service('Contacts', function ($http,$timeout,$q) {
return {
getData: function() {
var defer = $q.defer();
$http.get('../ListContacts')
.success(function(data) {
defer.resolve(data);
});
return defer.promise;
}
}
});


ContactsController, OtherControllers

$scope.contactsBook = {};
...
Contacts.getData().then(function(data) {
$scope.contactsBook = data;
});


I found the above method somewhere in SO itself. I used it because I don't want to use separate module for Contacts.

I can get data at page load. I can update my contacts at server through ajax posts (from ContactsController). Now I only need a way to update(/refresh) the list automatically in all controllers. How can I achieve that.

I found these three links related but being a newbie I'm unable to figure my way out.

Answer

While it is understandable that you may not want to update your current architecture, it may be necessary to adjust your calls slightly if you want to be able to easily share data between controllers via a service.

One flexible approach is to store the data in your service and register watchers in each controller. This allows you to call the service update from one controller (the Contacts controller) and have the change be reflected in all consuming controllers. Note the service is mocked.

You can find the working plunker example here.

Contacts Service:

var app = angular.module('app', []);    
app.service('contactsService', function ($http) {
    var contacts = [];

    return {
        loadData: function() {
            var mockGet = $q.defer();

            var data = [
              { id: 1, name: 'Jack' },
              { id: 2, name: 'Jill' }
            ];

            contacts = data;
            mockGet.resolve(contacts);
            return mockGet.promise; 
        },
        retrieveNewData: function() {
            var mockGet = $q.defer();

            var data = [
              { id: 1, name: 'Jack' },
              { id: 2, name: 'Jill' },
              { id: 3, name: 'Bob' },
              { id: 4, name: 'Susan' }
            ];

            contacts = data;
            mockGet.resolve(contacts);
            return mockGet.promise; 
        },
        getContacts: function () {
          return contacts;
        }
    }
});

Contacts Controller:

app.controller('ContactsCtrl', ['$scope', 'contactsService', 
  function ($scope, contactsService) {
    var vm = this;
    vm.contacts = [];

    vm.loadData = loadData;
    vm.retrieveNewData = retrieveNewData;


    $scope.$watch(angular.bind(contactsService, function () {
        return contactsService.getContacts(); 
      }), function (newVal) {
        vm.contacts = newVal;
    });


    function loadData() {
      contactsService.loadData();
    }

    function retrieveNewData() {
      contactsService.retrieveNewData(); 
    }
  }
]);

Other Controller:

app.controller('OtherCtrl', ['$scope', 'contactsService',
  function($scope, contactsService) {
     var vm = this;
     vm.contacts = [];

     $scope.$watch(angular.bind(contactsService, function () {
        return contactsService.getContacts(); 
      }), function (newVal) {
        vm.contacts = newVal;
    });
  }
]);