1

UPDATE

My controller loads data from two services, and the directive is linked before one of the services has returned data. So I think I need to find a way to prevent loading the directive until the variable from the second service has actually been populated.

What is the best way to handle that?

Original question:

I have a scope with an array of objects, and also a single integer. So, in the controller, something like this:

$scope.array = [
    {title: 'foo', first: 'spam', second: 'eggs'}, 
    {title: 'bar', first: 'maps', second: 'sgge'}
];
$scope.another = 400;

I am using ngRepeat to pass values from each object in the array to a directive, like so:

<div ng-repeat="a in array" 
     my-directive="a.title" 
     my-first-val="a.first" 
     my-second-val="a.second"></div>

I would also like to bind another value, which is the same for all instances of the directive, but may also change:

<div ng-repeat="a in array" 
     my-directive="a.title" 
     my-first-val="a.first" 
     my-second-val="a.second"
     another-val="another"></div>

This final value never seems to bind properly [actually, it didn't bind because it hadn't populated yet - the syntax used here is fine]. Is this possible? Is there another way to bind a single value to all instances of a directive using ngRepeat?

4 Answers 4

4

To answer your updated question, I suggest you to use a $q promise. You could use a promise for loading the data of each service, and then the all method to combine the 2.

var promise1 = arrayService.getArray();
var promise2 = anotherService.getAnother();
var promise = $q.all([promise1, promise2]);
promise.then(function(data) {
  $scope.array = data[0];
  $scope.another = data[1];
});

EDIT: I understand from your comment that you want to know how to return a promise with a service. Code in 'arrayService' service

angular.module('yourApp').service('arrayService', function($q, someAsyncService) {
  this.getArray = function() {
    var deferred = $q.defer();
    someAsyncService.get(function(err, data){
      if (err) {
        deferred.reject(err);
      }
      else {
        deferred.resolve(data);
      }
    });
    return deferred.promise;
  };

});
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. That looks like what I need, except I take it from this pull request that we can't yet do this with services?
I don't think this pull request is related. You can have your services return promises by using the $q service. I updated my response to show you how you can turn a 'classic' async service (someAsyncService) into a promise-based service (arrayService) using $q.
2

ng-repeat creates a child scope, so you're another is different in every child scope. I would try defining another as the property of an object:

$scope.whatever.another = 400

html:

<div ng-repeat="a in array" 
 my-directive="a.title" 
 my-first-val="a.first" 
 my-second-val="a.second"
 another-val="whatever.another"></div>

1 Comment

Thanks for your help. See my update; the issue is coordinating two services with the rendering of the directive.
0

You might want to try to use expression evaluation with double braces

<div ng-repeat="a in array" 
 my-directive="a.title" 
 my-first-val="a.first" 
 my-second-val="a.second"
 another-val="{{another}}"></div>

angular would then try to evaluate the expression from the $scope instead of looking for the another variable from within the child scope created by ng-repeat

Comments

0

in response to the updated question one approach you could take if you have access to the directive and can change it is to add a scope.$watch to the another-val attribute in the link or controller function

            scope.$watch('anotherVal', function(newVal) {
                //do something here...
            });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.