Search code examples
angularjsangularjs-ng-includeangular-ng-if

Use ng-if with ng-include to recreate scope


I have an ng-include inside of an ng-repeat:

<div ng-repeat="tab in tabs" ng-show="tab.active">
  <div ng-include="tab.url" class="no-padding no-margin"></div>
</div>

I only want the contents loaded into the DOM if the user clicks on the tab, so I am using an ng-if around the ng-include:

<div ng-repeat="tab in tabs" ng-show="tab.active">
    <div ng-if="tab.loaded">
        <div ng-include="tab.url" class="no-padding no-margin"></div>
    </div>
</div>

This part is working fine. However, I have one tab that requires dynamic content, so each time a user clicks on the tab, I need the scope for that controller to be recreated.

Based on my understanding, I can also use ng-if to remove/recreate DOM elements. According to the ng-if documentation:

The ngIf directive removes or recreates a portion of the DOM tree based on an {expression}

...

when an element is removed using ngIf its scope is destroyed and a new scope is created when the element is restored

I've added the code to set the loaded property of the dynamic tab to false which should remove it's contents from the DOM.

I then set it back to true, so that the scope is recreated, but I cannot get the scope to be created again.

Is my approach correct, or is there something besides ng-if that I can use for my purpose.


Solution

  • Why do you need to "recreate" the scope? If the attribute of ngInclude changes in the scope, the other page will be included and will recompile all the html. Please describe why you need to do that as the reason could be wrong.

    Otherwise, indeed having ngIf evaluate to false will remove the element. But only if it is not set to true immediately after, as angular only refresh the DOM (your HTML) when it has the opportunity to do so, i.e. after the current synchronous block of code.

    This will not have any effect:

    $scope.theTab.loaded = false;
    $scope.theTab.loaded = true;
    // Now Angular enter a digest cycle and see that theTab.loaded has not changed.
    

    This will:

    $scope.theTab.loaded = false;
    // $timeout will wait for a digest cycle before executing the code
    // Angular will remove the tab from the DOM
    $timeout(function() {
      $scope.theTab.loaded = true;
      // Here a second digest cycle happen, angular will put the tab back into the DOM
    });