Using function with ng-repeat causing infinite dig

2019-09-14 21:11发布

问题:

I have the following piece of code.

https://plnkr.co/edit/Tt7sWW06GG08tdJu72Fg?p=preview. Please expand the window fully to see the whole view.

I have categories and sub-categories to display in a navbar as shown in the above plunkr. Each category has services/sub-categories to display.

I am using 2 nested ng-repeats and the inner one is using the value from the parent iteration of ng-repeat. I have attached a function getServicesByCategory to the inner ng-repeat that calls getServicesByCategoryfrom the DocumentsFactory and resolves the promise to return data in an array object subcategories, which eventually should get iterated by inner ng-repeat.

The categories are displaying fine but the sub-categories are not.

There are 2 problems with this.

1). The subcategories are being shown the same for every category, and the ones being shown belong to the last category in the outer ng-repeat iteration i.e Utility Services. Instead each category should shows it's own sub-categories.

2). The console shows multiple errors of infinite digest cycle aborting due to attempts exceeding than 10 with these errors http://errors.angularjs.org/1.5.6/$rootScope/infdig?p0=10&p1=%5B%5D repeatedly in console. The method getServicesByCategoryis being called in an infinite loop triggering multiple digest cycles.

Seems like a simple category problem complicated by Angular's dirty checking and digest cycles.

I read multiple threads and posts suggesting to not return a new object inside the function associated with ng-repeat which I am not. I am returning the reference of subcategories.

The inner ng-repeat is dependent upon the data from outer one. Binding a function to ng-repeat was only option for me. Is this the right approach? The API's to fetch categories and subcategories are different and I dont have the flexibility to change them. I have been unable to come up with a solution. Just want to right sub-categories against each category.

Any help will be highly appreciated!

Note: Open the view in full window to see the navbar on the left.

回答1:

The solution here is to get all the data you need and create an array of categories, each one containing its own sub categories. And use this object in the nested ng-repeats.

Please check my updated version of your plunker:

https://plnkr.co/edit/BaHOcI4Qa8t5CkbshyCX

As you can see, I use:

ng-repeat="category in documents.categories"

In the outer ng-repeat and:

ng-repeat="service in category.subCategories"

In the inner one.

In the Controller I build the category.subCategories in the following way:

documentsFactory
  .getCategories() // Get categories
  .then(function(response) { // Extract them from the response
    return response.data.subCategory;
  })
  .then(getSubcategories) // For every catgory, get its own subcategory
  .then(function(categories) { // Add categories to the $scope
    self.categories = categories;
  });

Where getSubcategories is:

function getSubcategories(categories) {
  console.log(categories)
  var retrievSubcategories = categories.map(function(category) { // Create a promise to get the subcategories for every category
    return documentsFactory
      .getServicesByCategory(category.name) // Get the subcategories for the given category
      .then(function(response) {
        category.subCategories = response.data.documents; // Add subgategories to the category
        return category;
      });
  });
  return $q.all(retrievSubcategories) // Return a promise resolve only when all the subcategories for every category are retrieved
}