0

I have a plain angular application which adds variables to the scope and simply display them. Which is simple and working.

But there is a part of the page that does not run in angular (practically it is a jQuery plugin), so I have to use $compile to enable directive usage in the rendered HTML. However, in this HTML, the ng-if directive does not work and always evaluates to false and disappeared. But when using ng-show, things are displayed/hidden as expected.

What could be the reason and how is a fix possible?

Plunker: https://plnkr.co/edit/kWp4CaED9ZFaOmY36ixT?p=preview

  <div ng-controller="GreeterController">
    <strong>$scope</strong><br>
    constTrue: {{constTrue}}<br>
    ng-if="constTrue": <span ng-if="constTrue">Yes</span><br>
    ng-show="constTrue": <span ng-show="constTrue">Yes</span><br>
    returnTrue(): {{returnTrue()}}<br>
    ng-if="returnTrue()": <span ng-if="returnTrue()">Yes</span><br>
    ng-show="returnTrue()": <span ng-show="returnTrue()">Yes</span><br>
  </div>

  <hr>

  <div id="outsideController">
    <strong>$compile</strong><br>
    constTrue: {{constTrue}}<br>
    ng-if="constTrue": <span ng-if="constTrue">Yes</span><br>
    ng-show="constTrue": <span ng-show="constTrue">Yes</span><br>
    returnTrue(): {{returnTrue()}}<br>
    ng-if="returnTrue()": <span ng-if="returnTrue()">Yes</span><br>
    ng-show="returnTrue()": <span ng-show="returnTrue()">Yes</span><br>
  </div>
app.controller('GreeterController', ['$scope', '$compile', '$timeout', function($scope, $compile, $timeout) {
  $scope.constTrue = true;
  $scope.returnTrue = function(){ return true }

  var outsideController = document.getElementById('outsideController');
  $compile(outsideController)($scope);
}]);

RESULT

$scope

constTrue: true
ng-if="constTrue": Yes
ng-show="constTrue": Yes
returnTrue(): true
ng-if="returnTrue()": Yes
ng-show="returnTrue()": Yes

$compile

constTrue: true
ng-if="constTrue": 
ng-show="constTrue": Yes
returnTrue(): true
ng-if="returnTrue()": 
ng-show="returnTrue()": Yes
georgeawg
  • 48,608
  • 13
  • 72
  • 95
Eric Wong
  • 1,388
  • 7
  • 17

1 Answers1

1

The problem occurs because the element is being compiled twice. Once when the app bootstraps and again with the $compile service in the controller.

The solution is to declare to the AngularJS framework that the element not be compiled when bootstrapping.

Use the ng-non-bindable directive:

<div ng-non-bindable>
  <div id="outsideController">
    <strong>$compile</strong><br>
    constTrue: {{constTrue}}<br>
    ng-if="constTrue": <span ng-if="constTrue">Yes</span><br>
    ng-show="constTrue": <span ng-show="constTrue">Yes</span><br>
    returnTrue(): {{returnTrue()}}<br>
    ng-if="returnTrue()": <span ng-if="returnTrue()">Yes</span><br>
    ng-show="returnTrue()": <span ng-show="returnTrue()">Yes</span><br>
  </div>
</div>

Then when the controller compiles the element is will be clean and unmodified.

The DEMO on PLNKR

For more information, see

georgeawg
  • 48,608
  • 13
  • 72
  • 95