angular / angular

Deliver web apps with confidence 🚀
https://angular.dev
MIT License
95.93k stars 25.36k forks source link

Angular 6 Animation is not working in IE #24923

Closed pablopandolfi closed 5 years ago

pablopandolfi commented 6 years ago

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[x ] Bug report  
[ ] Performance issue
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question
[ ] Other... Please describe:

Current behavior

I have the following animation in Angular 6.


slide-in-out-animation.ts

    // import the required animation functions from the angular animations module
import { trigger, state, animate, transition, style } from '@angular/animations';

export const slideInOutAnimation =
  // trigger name for attaching this animation to an element using the [@triggerName] syntax
  trigger('slideInOutAnimation', [

    // end state styles for route container (host)
    state('*', style({
      // the view covers the whole screen with a semi tranparent background
      position: 'fixed',
      zIndex: 6,
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: 'rgba(0, 0, 0, 0.8)'
    })),

    // route 'enter' transition
    transition(':enter', [

      // styles at start of transition
      style({
        // start with the content positioned off the right of the screen, 
        // -400% is required instead of -100% because the negative position adds to the width of the element
        right: '-400%',
        zIndex: 6,

        // start with background opacity set to 0 (invisible)
        backgroundColor: 'rgba(0, 0, 0, 0)'
      }),

      // animation and styles at end of transition
      animate('.5s ease-in-out', style({
        // transition the right position to 0 which slides the content into view
        right: 0,
        zIndex: 6,

        // transition the background opacity to 0.8 to fade it in
        backgroundColor: 'rgba(0, 0, 0, 0.8)'
      }))
    ]),

    // route 'leave' transition
    transition(':leave', [
      // animation and styles at end of transition
      animate('.5s ease-in-out', style({
        zIndex:6,
        // transition the right position to -400% which slides the content out of view
        right: '-400%',

        // transition the background opacity to 0 to fade it out
        backgroundColor: 'rgba(0, 0, 0, 0)'
      }))
    ])
  ]);

When I want to use the animation in a Component:


@Component({
      selector: 'app-example-edit',
      templateUrl: './example-edit.component.html',
      styleUrls: ['./example-edit.component.css'],

      // make slide in/out animation available to this component
      animations: [slideInOutAnimation],

      // attach the slide in/out animation to the host (root) element of this component
      host: { '[@slideInOutAnimation]': '' }
    })
export class ExampleComponent {

}

In parent-component.html I have the html

<a href="#" routerLink="add">Add</a>
<div class="view-side-form">
  <router-outlet></router-outlet>
</div>

In the parentcomponent I have a link to add a element. When the user click in the link. The content of examplecomponent is loaded using the animation. In chrome is working perfect. But in Internet Explorer the animation is not working. Also, the animation is working perfect using Angular5 in Chrome and IE. The problem is when i want to use it with Angular 6.

This is my package.json file


{
  "name": "app-web",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^6.0.3",
    "@angular/cdk": "^6.3.3",
    "@angular/common": "^6.0.3",
    "@angular/compiler": "^6.0.3",
    "@angular/core": "^6.0.3",
    "@angular/forms": "^6.0.3",
    "@angular/http": "^6.0.3",
    "@angular/material": "^6.3.3",
    "@angular/platform-browser": "^6.0.3",
    "@angular/platform-browser-dynamic": "^6.0.3",
    "@angular/router": "^6.0.3",
    "@types/jquery": "^3.3.4",
    "angular2-moment": "^1.9.0",
    "angular2-multiselect-dropdown": "^2.9.0",
    "angular2-toaster": "^6.1.0",
    "bootstrap": "^3.3.7",
    "chart.js": "^2.7.2",
    "core-js": "^2.5.4",
    "font-awesome": "^4.7.0",
    "jquery": "^3.3.1",
    "ng2-bs3-modal": "^0.15.0",
    "ng2-charts": "^1.6.0",
    "ng2-datetime": "^1.4.0",
    "ngx-bootstrap": "^3.0.1",
    "rxjs": "^6.0.0",
    "web-animations-js": "^2.3.1",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@angular/compiler-cli": "^6.0.3",
    "@angular-devkit/build-angular": "~0.6.8",
    "typescript": "~2.7.2",
    "@angular/cli": "~6.0.8",
    "@angular/language-service": "^6.0.3",
    "@types/jasmine": "~2.8.6",
    "@types/jasminewd2": "~2.0.3",
    "@types/node": "~8.9.4",
    "codelyzer": "~4.2.1",
    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~1.7.1",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.0",
    "karma-jasmine": "~1.1.1",
    "karma-jasmine-html-reporter": "^0.2.2",
    "protractor": "~5.3.0",
    "ts-node": "~5.0.1",
    "tslint": "~5.9.1"
  }
}

polyfills.ts


/** IE9, IE10 and IE11 requires all of the following polyfills. **/
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/weak-map';
import 'core-js/es6/set';

/** IE10 and IE11 requires the following for NgClass support on SVG elements */
// import 'classlist.js';  // Run `npm install --save classlist.js`.

/** IE10 and IE11 requires the following for the Reflect API. */
// import 'core-js/es6/reflect';

/** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect';

/**
 * Web Animations `@angular/platform-browser/animations`
 * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
 * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
 **/
import 'web-animations-js';  // Run `npm install --save web-animations-js`.

/**
 * By default, zone.js will patch all possible macroTask and DomEvents
 * user can disable parts of macroTask/DomEvents patch by setting following flags
 */

 // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
 // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
 // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames

 /*
 * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
 * with the following flag, it will bypass `zone.js` patch for IE/Edge
 */
// (window as any).__Zone_enable_cross_context_check = true;

/***************************************************************************************************
 * Zone JS is required by default for Angular itself.
 */
import 'zone.js/dist/zone';  // Included with Angular CLI.

In Angular5 is working perfect in all browsers, but when I want to migrate to Angular6 i have problems with IE. No errors in IE console.

Minimal reproduction of the problem with instructions

You can reproduce the problem in the following link: https://stackblitz.com/edit/angular-grryts

opetriienko commented 6 years ago

There is also a problem in IE that ng-components aren't removed when routing animation is done. Thus, all ng-componets stay in the DOM even if we left the route. Not sure if a separate ticket should be created for that.

gurkn commented 6 years ago

We had a similar problem as in the first post, solved it by adding this to our polyfills:

if (!Element.prototype.matches) {
  Element.prototype.matches = Element.prototype.msMatchesSelector;
}
pablopandolfi commented 6 years ago

Hi, I have tested using https://stackblitz.com/edit/angular-grryts (link added in the bug description), but i wont able to resolve the problem. Could you try to test with the link? thanks

gurkn commented 6 years ago

Hey. Yeah, you're right, it doesn't solve the actual animation. We probably had a different bug where the animation would throw an error in IE11 if if we didn't add the polyfill. Sorry.

pablopandolfi commented 6 years ago

Hi, someone has a workaround that can help to me ? Or some other solution that i can use for implementing the same animation ? thanks

willyboy commented 6 years ago

There is also a problem in IE that ng-components aren't removed when routing animation is done. Thus, all ng-componets stay in the DOM even if we left the route. Not sure if a separate ticket should be created for that.

@opetriienko Is there an issue open for this? I can't find one and am experiencing the same.

jackmusick commented 6 years ago

There is also a problem in IE that ng-components aren't removed when routing animation is done. Thus, all ng-componets stay in the DOM even if we left the route. Not sure if a separate ticket should be created for that.

@opetriienko Is there an issue open for this? I can't find one and am experiencing the same.

Same here. I've tried all the proposed solutions and I'm having this with routing transitions.

willyboy commented 6 years ago

@jackmusick After what feels like a lifetime of debugging, I know what was causing this for me so maybe it will help you.

I have dynamic components in my template that I don't want to be removed from the DOM while the page is being navigated away from (it looks weird). In order to prevent them from being hidden, I added a block to my animation that look like this: query(':leave ng-component', [animate('1.5s')], {optional: true})

This worked in all browsers besides IE. So I dug into the code. Because IE requires polyfilling, it uses CssKeyFrames instead of WebAnimations. CssKeyFrames generates CSS for my code that looks like this:

@keyframes gen_css_kf_1 {
    0% {}
    100%{}
}

Angular is relying on the animationend event to remove elements from the DOM. IE never triggers the animation end event when there are no animatable properties in the block (for instance: display block -> display block also does not trigger the animationend event).

Until Angular puts in a fix, I have resolved this by adding animatable properties to my ng-component query:

query(`:leave ng-component`, [animate('1.5s', style({ transform: 'translateY(0%)' }))], { optional: true })
jackmusick commented 5 years ago

@willyboy I tried what you suggested and I don't think it helped. Here's what I'm using for my router transition:

export const RouterAnimation = trigger('routerTransition', [
    transition('* => *', [
        // Initial state of new route
        query(':enter',
            style({
                position: 'fixed',
                width: '100%',
                transform: 'translateX(-100%)'
            }),
            { optional: true }),

        // move page off screen right on leave
        query(':leave',
            animate('200ms ease',
                style({
                    position: 'fixed',
                    width: '100%',
                    transform: 'translateX(100%)'
                })
            ),
            { optional: true }),

        // move page in screen from left to right
        query(':enter',
            animate('200ms ease',
                style({
                    opacity: 0.10,
                    transform: 'translateX(0%)'
                })
            ),
            { optional: true }),
        query(':enter', animateChild(), { optional: true }),
    ])
]);

I can't say I understand Angular Animations fully, but I will say that this worked in Angular 5. The intended result is to fade and transition the main content in the router, left to right. This works fine in Chrome, but in IE and Edge, it leaves the object on the screen and the incoming route is left faded a little on the left. If I navigate back to the previous route, it's appended to the top of the screen, effectively creating two components.

foxx9 commented 5 years ago

This was a surprise for me to upgrade from angular 4 with purposely no animation polyfill to angular 6.

I did not include it because it was not rendering well on IE., but now that the polyfill is not needed, my app on IE is a disaster with broken animation and components not being destroyed.

This is an important regression.

theodorejb commented 5 years ago

I was able to fix the "Object doesn't support property or method 'matches'" error in Internet Explorer by setting node: {process: false} in my Webpack config. See https://github.com/angular/angular/issues/24769#issuecomment-405498008.

madhav5589 commented 5 years ago

@theodorejb It worked for me as well. After upgrading Angular project from 5 to 6, I started started having this issue on IE11.

jackmusick commented 5 years ago

@theodorejb @madhav5589 Are either of you using the CLI? I'm still not sure how I customize webpack if I'm using it.

madhav5589 commented 5 years ago

@jackmusick No, I don't use CLI. I updated webpack.config.js directly.

theodorejb commented 5 years ago

@jackmusick I'm not using the CLI, either. My understanding is that the CLI is supposed to take care of setting up the Webpack config correctly, though. If the Angular team considers disabling Webpack's node process option to be the correct solution, then I would expect the CLI to do this out-of-the-box.

ravo10 commented 5 years ago

Try adding the keyframes function like this. Works for me:

export const slideInOutAnimation =
  trigger('slideInOutAnimation', [
    state('*', style({
      position: 'fixed',
      zIndex: 6,
      top: 0,
      left: 0,
      right: 0,
      bottom: 0,
      backgroundColor: 'rgba(0, 0, 0, 0.8)'
    })),
    transition(':enter', [
      style({
        right: '-400%',
        backgroundColor: 'rgba(0, 0, 0, 0)'
      }),
      animate('.5s ease-in-out', keyframes([
        style({
          right: 0,
          backgroundColor: 'rgba(0, 0, 0, 0.8)'
        })
      ]))
    ]),
    transition(':leave', [
      animate('.5s ease-in-out', keyframes([
        style({
          right: '-400%',
          backgroundColor: 'rgba(0, 0, 0, 0)'
        })
      ]))
    ])
  ]);
byvlstr commented 5 years ago

Hi, on our side, everything is working in IE11 up to animations@7.2.7. From 7.2.8 declared animations do not work anymore in IE.

Our usage: trigger('isVisibleChanged', [ \ state('true', style({opacity: 1, display: 'block'})), state('false', style({opacity: 0, display: 'none'})), transition('1 => 0', animate('900ms')), transition('0 => 1', animate('900ms')) ])

And in the template: <div [@isVisibleChanged]="documents.content.length > 0">

angular-automatic-lock-bot[bot] commented 5 years ago

This issue has been automatically locked due to inactivity. Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.