NativeScript / nativescript-angular

Integrating NativeScript with Angular
http://docs.nativescript.org/angular/tutorial/ng-chapter-0
Apache License 2.0
1.22k stars 241 forks source link

*ngIf should wait for an animation to complete before removing a node #953

Open calebkiage opened 7 years ago

calebkiage commented 7 years ago

I have the following animation defined

trigger('ngIfAnimation', [
    transition('* <=> *', [
        query(':enter', style({opacity: 0, transform: 'translateY(-200px)'}), {optional: true}),
        query(':leave', style({opacity: 1, transform: 'none'}), {optional: true}),
        group([
            query(':leave', animate(1000, style({opacity: 0, transform: 'translateY(-200px)'})), {optional: true}),
            query(':enter', animate(1000, style({opacity: 1, transform: 'none'})), {optional: true})
        ])
    ])
])

and the following structure in the template

<StackLayout class="sidedrawer-content" [@ngIfAnimation]="showLogin ? '1' : '2'">
  <StackLayout *ngIf="showLogin">
    <Label class="p-16" text="Login"></Label>
  </StackLayout>
  <ListView [items]="navigationItems" *ngIf="!showLogin" separatorColor="transparent">
    <ng-template let-item="item">
    <GridLayout columns="auto, *"
                class="sidedrawer-list-item sidedrawer-list-item-{{item.name}}">
        <Label row="0" col="0" [text]="item.icon" class="fa"></Label>
        <Label row="0" col="1" [text]="item.title" textWrap="true"></Label>
    </GridLayout>
    </ng-template>
  </ListView>
</StackLayout>

When I run the app, the leave animation doesn't run because the node is immediately removed from the view. If a node is queried, it should stay in the view until the animation completes. This is how animation behaves in the browser.

package.json file

{
  "description": "NativeScript Application",
  "license": "SEE LICENSE IN <your-license-filename>",
  "readme": "NativeScript Application",
  "repository": "<fill-your-repository-here>",
  "nativescript": {
    "id": "org.nativescript.testapp",
    "tns-android": {
      "version": "3.1.1"
    }
  },
  "scripts": {
    "lint": "tslint \"app/**/*.ts\"",
    "ns-bundle": "ns-bundle",
    "start-android-bundle": "npm run ns-bundle --android --run-app",
    "start-ios-bundle": "npm run ns-bundle --ios --run-app",
    "build-android-bundle": "npm run ns-bundle --android --build-app",
    "build-ios-bundle": "npm run ns-bundle --ios --build-app",
    "publish-ios-bundle": "npm run ns-bundle --ios --publish-app",
    "generate-android-snapshot": "generate-android-snapshot --targetArchs arm,arm64,ia32 --install"
  },
  "dependencies": {
    "@angular/animations": "~4.2.6",
    "@angular/common": "~4.2.6",
    "@angular/compiler": "~4.2.6",
    "@angular/core": "~4.2.6",
    "@angular/forms": "~4.2.6",
    "@angular/http": "~4.2.6",
    "@angular/platform-browser": "~4.2.6",
    "@angular/router": "~4.2.6",
    "nativescript-angular": "~4.2.0",
    "nativescript-telerik-ui": "^3.0.0",
    "nativescript-theme-core": "~1.0.2",
    "reflect-metadata": "~0.1.8",
    "rxjs": "~5.4.0",
    "tns-core-modules": "~3.1.0",
    "zone.js": "~0.8.2"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~4.2.6",
    "@ngtools/webpack": "~1.5.0",
    "babel-traverse": "6.26.0",
    "babel-types": "6.26.0",
    "babylon": "6.18.0",
    "codelyzer": "^3.0.1",
    "copy-webpack-plugin": "~4.0.1",
    "extract-text-webpack-plugin": "~3.0.0",
    "lazy": "1.0.11",
    "nativescript-css-loader": "~0.26.0",
    "nativescript-dev-sass": "^1.2.0",
    "nativescript-dev-typescript": "~0.5.0",
    "nativescript-dev-webpack": "^0.7.3",
    "node-sass": "*",
    "raw-loader": "~0.5.1",
    "resolve-url-loader": "~2.1.0",
    "tslint": "^5.4.3",
    "typescript": "~2.4.0",
    "webpack": "~3.2.0",
    "webpack-bundle-analyzer": "^2.8.2",
    "webpack-sources": "~1.0.1"
  }
}
andreferraz commented 7 years ago

That would be extremely useful. Anything that removes something from the DOM should wait the animation completes or have an option for allow that.

jzgoda commented 2 years ago

I know this issue is over 4 year old, but is there any workaround for getting a :leave animation working?

jzgoda commented 2 years ago

Well, I found my own workaround using animation states without an ngIf involved:

import {
  trigger,
  transition,
  style,
  animate,
  state,
} from "@angular/animations";
import { Component } from "@angular/core";

@Component({
  selector: "ns-app",
  template: `<GridLayout rows="*, auto, auto" backgroundColor="#ffffff">
    <StackLayout row="0" rowSpan="3" verticalAlignment="center">
      <Button text="Tap Me" (tap)="show = !show" class="btn -primary"></Button>
    </StackLayout>
    <GridLayout
      row="1"
      class="notification"
      [@stateFade]="show ? 'show' : 'hide'"
    >
      <Label text="Hello!"></Label>
    </GridLayout>
  </GridLayout>`,
  styles: [
    "Button.-primary { font-size: 18; background-color: #0d2d6c; color: #ffffff; }",
    ".notification { color: #ffffff; font-size: 26; text-align: center; padding: 10; background-color: #0d2d6c; }",
  ],
  animations: [
    trigger("stateFade", [
      state("show", style({ opacity: 1, transform: "translateY(0)" })),
      state("hide", style({ opacity: 0, transform: "translateY(70)" })),
      transition("show => hide", [
        animate(
          "0.5s ease-in",
          style({ opacity: 0, transform: "translateY(70)" })
        ),
      ]),
      transition("hide => show", [
        animate(
          "0.5s ease-out",
          style({ opacity: 1, transform: "translateY(0)" })
        ),
      ]),
    ]),
  ],
})
export class AppComponent {
  show: boolean = false;
}