Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 1.x ngAnimate in Shadow DOM doesn't register animation times or add enter/leave classes

I've been trying to work out solutions for a few hours now - all the duplicates in SO don't seem to work for me as they mostly recommend either trying different versions of ng-animate/angular or adding the transition/animation in the relevant classes so that ngAnimate can handle their timings right.

My problem is that all of this was working, and I had all the properties in the correct locations - but now I am migrating our Chrome extension to work under a Shadow DOM encapsulation.

Notes:

  • Shadow DOM is probably the culprit, but I'm not sure why or how to fix it. It might also be irrelevant or only play a minor part in the actual problem (it is probably due to bad DOM handling in Shadow DOM + angular)
  • I am bootstrapping my app manually later in the lifecycle of the extension injection since it is supposed to only start up after a callback. This might also be the culprit

Here is a plunker - I think I have the case isolated as much as I could here. Clicking the links should open/close the divs after them in a slide down/up animation, respectively. Currently they just open up immediately.

Here are the relevant styles:

.view-container {
  position: absolute;
  top: 70px;
  bottom: 0;
  background: white;
  transition: all 0.4s 0.2s ease-in-out;
  overflow-y: hidden;
  // slide animation
  &,
  &.ng-hide-remove,
  &.ng-hide-remove-active {
    max-height: 500px;
  }

  &.ng-hide {
    max-height: 0;
  }
}

Here is the template:

<div ng-show="rchCtrl.view == 'flag'"
  class="view-container">
  <div ng-include="'/templates/extension/article-flag-form.html'"
    ng-if="rchCtrl.view == 'flag'"
    ng-controller="ArticleFlagCtrl as flg"
    class="article-flag"></div>
</div>

Bower file:

"dependencies": {
    "jquery": "^2.2.1",
    "trackjs": "^2.8.3",
    "angular": "^1.6.0",
    "qtip2": "^2.2.1",
    "ng-qtip2": "1.3.3",
    "angular-ui-router": "^0.2.18",
    "angular-cookies": "^1.6.0",
    "angular-resource": "^1.6.0",
    "bootstrap": "^3.3.7",
    "angular-animate": "^1.6.0"
  },
  "resolutions": {
    "angular": "1.6.6"
  }

My angular init section:

app = angular.module(APP_NAME, ['template-cache', 'ui.router', 'ngCookies', 'geCommon', 'ngAnimate'])

// ...

angular.bootstrap(shadow.querySelector('#ge-ext'), [ APP_NAME ], { debugInfoEnabled: true })
angular.resumeBootstrap()

But after all this, the intermediate classes are never added/removed, and the animation isn't working - hide/show display is immediate.

like image 432
casraf Avatar asked Aug 23 '17 13:08

casraf


People also ask

When animations are disabled in Angular?

To disable all animations for an Angular app, place the @. disabled host binding on the topmost Angular component. NOTE: Disabling animations application-wide is useful during end-to-end (E2E) testing.

How do you define transition between two states in Angular?

Transition basically means navigating from the current state to a new state. In angular, the transition is an animation-specific function which is used in angular's animation DSL language. Transition declares the sequence of animation steps that will be executed when the entered value is satisfied.

What is transition function in Angular?

The State Change Expression instructs Angular when to run the transition's animations, it can either be. a string with a specific syntax. or a function that compares the previous and current state (value of the expression bound to the element's trigger) and returns true if the transition should occur or false otherwise.


1 Answers

Take a look if this is what you are trying to achieve:

https://plnkr.co/edit/0rmEfPlsn3GsK6rtLalP?p=preview

I did some tweaks on the menu.html and style.css. Basically, what I did was remove things like ng-hide/ng-show from the elements that were supposed to have animation and instead I've put ng-class to manipulate the visibility while maintaning the animation. The reason that ng-hide/ng-show aren't the best ideas for animation is that they apply display: block property to your element, thus any transition applied to them will not work. visiblity: visible/hidden is the key if you want to use css transitions.

// New styles
#menu li {
  transition: all 0.4s ease-in-out;
}

#menu li.invisible {
  height: 0;
  opacity: 0;
  visibility: hidden;
}

.article-feedback,
.article-flag {
  /* Zero height in normal start */
  height: 0;
  transition: all 0.4s ease-in-out;
}

.article-feedback.visible,
.article-flag.visible {
  /* When visible, height goes to 100px */
  height: 100px;
}
<ul id="menu"
  class="list-unstyled"
  ng-class="{'view-open': rchCtrl.view != null}"
  ng-show="rchCtrl.menuOpen"
  ng-controller="RelatedResearchesCtrl as rchCtrl">
  <li ng-class="{'invisible': rchCtrl.view && rchCtrl.view != 'feedback'}">
    <a fake-click
      ng-click="rchCtrl.openView('feedback')">
      Send feedback &amp; ideas
    </a>
    <span class="icon-close"
      ng-show="rchCtrl.view == 'feedback'"
      ng-click="rchCtrl.openView(null); $event.stopPropagation()">
      &times;
    </span>

    <!-- I've removed the ng-show and added ng-class, so transitions will work -->
    <div class="view-container">
      <div style="background: red;"
        ng-class="{'visible': rchCtrl.view == 'feedback'}"
        class="article-feedback"></div>
    </div>
  </li>
  <li ng-class="{'invisible': rchCtrl.view && rchCtrl.view != 'flag'}">
    <a fake-click
      ng-click="rchCtrl.openView('flag')">
      Flag this page
    </a>
    <span class="icon-close"
      ng-show="rchCtrl.view == 'flag'"
      ng-click="rchCtrl.openView(null); $event.stopPropagation()">
      &times;
    </span>
    <div class="view-container">

      <!-- I've removed the ng-show and added ng-class, so transitions will work -->
      <div style="background: blue;"
        ng-class="{'visible': rchCtrl.view == 'flag'}"
        class="article-flag"></div>
    </div>
  </li>
</ul>

Let me know if there's any other questions about my plnkr.

like image 58
Bruno Poeta Avatar answered Oct 14 '22 21:10

Bruno Poeta