Ian
Ian

Reputation: 2984

Angular initial transition of ng-show, using $timeout and $compile

I have a service that uses $compile to attach some HTML to the DOM. This HTML contains one ng-show with a transition for showing and hiding, and it starts with a falsy condition. The problem is when its attached to the DOM, it shows the hide transition. How can I avoid it? I have noticed that my controller calls this service inside a $timeout, only then the undesired transition ocurrs.

https://plnkr.co/edit/og0wrp6rZ65StXbufqLI?p=preview

angular
  .module('app', ['ngAnimate'])
  .directive('compileNgShowAnimation', ($timeout, $compile) => ({
    restrict: 'E',
    link: (scope, element) => {
      $timeout(() => {
        angular
          .element(element)
          .append($compile(`
            <div>
              Show: 
              <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow">
              <br />
              <div 
                class="check-element animate-show-hide"  
                ng-show="checked">
                I should show up only when the checkbox is checked.
              </div>
            </div>
          `)(scope))
      })
    }
  }))
.animate-show-hide.ng-hide {
  /*transform: translate3d(0,-100%, 0);*/
  opacity: 0;
}

.animate-show-hide:not(.ng-hide) {
  /*transform: translate3d(0,0, 0);*/
  opacity: 1;
}

.animate-show-hide.ng-hide-add,
.animate-show-hide.ng-hide-remove {
  transition: all linear 0.5s;
}

.check-element {
  border: 1px solid black;
  padding: 10px;
}

/*
Copyright 2017 Google Inc. All Rights Reserved.
Use of this source code is governed by an MIT-style license that
can be found in the LICENSE file at http://angular.io/license
*/
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular-animate.min.js"></script>
<body ng-app="app">

  <compile-ng-show-animation></compile-ng-show-animation>
  
</body>

Upvotes: 0

Views: 647

Answers (2)

An option is to make sure that the element is hidden by default by adding the ng-hide class to the div:

<div class="check-element animate-show-hide ng-hide" ng-show="checked">
     I should show up only when the checkbox is checked.
</div>

Then you wont get the brief visibility

https://plnkr.co/edit/Ik3BflLHwu3DXglOMOhX?p=preview

Upvotes: 1

Ernesto Schiavo
Ernesto Schiavo

Reputation: 1060

You can use a flag in order to apply class after some times, something like this:

angular
  .module('app', ['ngAnimate'])
  .directive('compileNgShowAnimation', ($rootScope, $compile, $document, $timeout) => ({
    restrict: 'E',
    link: (scope, element) => {
      $timeout(() => {
        scope.checked = false;
        scope.animate = false;

        angular
          .element(element)
          .append($compile(`
            <div>
              Show: 
              <input type="checkbox" ng-model="checked" aria-label="Toggle ngShow">
              <br />
              <div class="check-element {{animate ? 'animate-show-hide':''}}" ng-show="checked">
                I should show up only when the checkbox is checked.
              </div>
            </div>
          `)(scope))
      });
      $timeout(() => {

        scope.animate = true;
      },10);
    }
  }))

Upvotes: 0

Related Questions