Explanation:
The villain of the piece is the use of angular.injector
in the link function:
var injector = angular.injector(['ng', 'app']);
var lookupService = injector.get(scope.serviceName);
This code will create a new injector function instead of retrieving the one already created for your application when it was bootstrapped.
Services in Angular are singletons in the sense that they are only created once per injector. In your case this means that injector.get(scope.serviceName)
will return a new instance of the service and not the same instance as you possibly would've interacted with before.
The same goes for the $http
service that your lookupService
uses. In turn, $http
injects $rootScope
to trigger the digest cycle by calling $apply
on it after a XHR request. But as the $rootScope
will not be the same as for the rest of your application, the digest cycle will be in vain.
This is also the reason for the behaviors you are witnessing, and why an explicit call to scope.$digest()
helps, as it will trigger the digest cycle on the correct scope chain.
Solution:
Inject the $injector
service in your directive and use that to retrieve the service you want:
.directive('lookup', ['$injector',
function($injector) {
function link(scope, elem) {
var lookupService = $injector.get(scope.serviceName);