dcp3450
dcp3450

Reputation: 11187

In Angular, how can I use ng-repeat to pass a variable to that triggers it repeat number?

In my app I do a database call to get a list of elements to display using ng-reat, this works fine. Inside that list is another list. That depends on another DB call.

I'd like to pass an id and repeat an element the number of results I get back and output their data. Something like this:

<div ng-repeat="library in libraries">
    <p>Read our books:</p>
    <p ng-repeat="book in books">{{book.title}}</p>
</div>

I thought about this:

<p ng-repeat="book in getBooks({library.id}) track by $index">{{book.title}}</p>

this use something like this to trigger the number of repeats and the values:

$scope.getBooks = function(id){
    ...run my database query using the id...
    ...update my scope to include the books...
    ....**magic**...
}

but I'm not sure if that will work and how to update my scope to include the book title. I've used this to repeat an x number of times but not include an updated $scope

Upvotes: 0

Views: 210

Answers (1)

KnowHowSolutions
KnowHowSolutions

Reputation: 680

Along with Corbin, my solution would be to pre-load the data. Do that with an Angular factory object.

 angular.module('appName')
        .factory('DataManager', DataManager);

    function DataManager($log, $timeout, DataService) {
        var mngr, config = getConfig();  // any default values

        $log.debug('DataManager Init');

        mngr = {
            CurrentSearchTerm: null,
            Libraries: [],
            Abort: abort,
            GetData: getData  // Function call to get data.
        };

        // This call is your main ajax call, it could be one call to get the
        // full dataset of lib + books in json format.  Or multiple calls.
        function getData(){
            DataService.getData().then(function(response){
             //  ...parse data, etc...loop and :
             mngr.Libraries.push(parsedDataItem);
            };
        }


        return mngr;
   }

Inject that into your controller. Then you loop over that data.

<ul>
  <li ng-repeat="library in mngr.Libraries">
     <!-- now you should have library.Books which was already sent down in the factory payload. -->
  </li>
</ul>

Again to make your life a bit easier use a directive, each repeat push it's data into a directive:

<library data="library">

Which allows you to have a nice template and scope into just that one library.

angular('appName').directive('library',function(){
            return{
            restrict:'E',
            replace:true,
            templateUrl:'library.view.html',
            scope:{
                data:'='
            },
            controller:function($scope,$log){
                // Here $scope.data === library from your ngRepeat!
            }
        };
});

Lastly, if you wanted an ondemand loading of the books, in the directive you can add a method to your DataManager to 'getBooks' for that one library object.

Does that make more sense?

Upvotes: 0

Related Questions