Nativescript-angular: Animation transition void => * doesn't work on the first page

Created on 15 Sep 2018  路  8Comments  路  Source: NativeScript/nativescript-angular

If there is no issue for your problem, tell us about it

I want to use this simple animation:

animations: [
  trigger('flyInOut', [
    state('in', style({ transform: 'translateX(0)' })),
    transition('void => *', [
      style({ transform: 'translateX(100)' }),
      animate(1000)
    ]),
    transition('* => void', [
      animate(1000, style({ transform: 'translateX(-100)' }))
    ])
  ])
]

I try to setup it in a component which is rendered on the default route and the animation doesn't fire. Transition'void => *' doesn't work on the first load.
@flyInOut.start and @flyInOut.done events occur properly, but animation is not visible in the view. And animated element remains in transform: 'translateX(100)' state.

The problem occurs only on Android.

Please, provide the following version numbers that your issue occurs with:

  • CLI: 4.2.3
  • Cross-platform modules: 4.2.0
  • Runtime(s): 4.2.0
  • Plugin(s):
  "dependencies": {
    "@angular/animations": "~6.1.0",
    "@angular/common": "~6.1.0",
    "@angular/compiler": "~6.1.0",
    "@angular/core": "~6.1.0",
    "@angular/forms": "~6.1.0",
    "@angular/http": "~6.1.0",
    "@angular/platform-browser": "~6.1.0",
    "@angular/platform-browser-dynamic": "~6.1.0",
    "@angular/router": "~6.1.0",
    "nativescript-angular": "^6.1.0",
    "nativescript-theme-core": "~1.0.4",
    "reflect-metadata": "~0.1.10",
    "rxjs": "^6.0.0",
    "tns-core-modules": "^4.2.0",
    "zone.js": "^0.8.26"
  },
  "devDependencies": {
    "@angular/compiler-cli": "~6.1.0",
    "@ngtools/webpack": "~6.2.0",
    "@types/chai": "~4.1.3",
    "@types/mocha": "~5.2.1",
    "@types/node": "^7.0.5",
    "babel-traverse": "6.25.0",
    "babel-types": "6.25.0",
    "babylon": "6.17.4",
    "lazy": "1.0.11",
    "nativescript-css-loader": "~0.26.0",
    "nativescript-dev-appium": "next",
    "nativescript-dev-typescript": "^0.7.3",
    "nativescript-dev-webpack": "^0.16.0",
    "typescript": "~2.7.2"
  },

Please, tell us how to recreate the issue in as much detail as possible.

Launch playground app on android device.

Is there any code involved?

https://play.nativescript.org/?template=play-ng&id=ZoWGlW

animations

All 8 comments

possibly related to using wildcard issue

Is there a workaround to this?

I tried using an explicit state instead of * and still doesn't work:

    animations: [
        trigger('brandsflyIn', [
            state("in", style({ transform: "translateX(0)" })),
            transition('void => in', [
                style({ transform: 'translateX(500)' }),
                animate('500ms 500ms ease-in', style({ transform: 'translateX(0)' }))
            ]),
        ]),
    ]
    <FlexboxLayout height="54" flexDirection="row" justifyContent="flex-start"
        alignItems="stretch" flexWrap="nowrap">
        <GridLayout [@brandsflyIn]="'in'" height="54" class="small-card round-border"
            backgroundColor="#F2F2F2"
            *ngFor="let brand of ['adidas','nike','newbalance','ua','fila','lacoste','sketchers','jordan','levis']; let i = index">
            <Label text="{{brand}}"></Label>
        </GridLayout>
    </FlexboxLayout>

Full playground here

I have the same issue. It just doesn't work on the first page.

@rynop a simple solution is to set a *ngIf and make the element visible after a few milliseconds using setTimeout.

Thanks that worked, but man that is a bummer to have to manage state for every animation on page load.

@NickIliev is your gut feel that this is a hard fix? Or is this just low priority..

@vahidvdn actually I lied, I didn't get it working. It works on 2nd page load (like HMR refresh) but I can't get it to work on 1st page load (ex: when app 1st opens). Do you have a working example you can point me to?

Here is what I'm doing:

        <ScrollView height="54" orientation="horizontal">
            <FlexboxLayout *ngIf="startLoadAnimations" height="54" flexDirection="row" justifyContent="flex-start"
                alignItems="stretch" flexWrap="nowrap">
                <GridLayout [@brandsflyIn]="'in'" height="54" class="small-card round-border" backgroundColor="#F2F2F2"
                    *ngFor="let brand of ['adidas','nike','newbalance','ua','fila','lacoste','sketchers','jordan','levis']; let i = index">
                    <Image horizontalAlignment="center" verticalAlignment="center" src="~/images/brands/{{brand}}.png"></Image>
                </GridLayout>
            </FlexboxLayout>
        </ScrollView>
...
    animations: [       
        trigger('brandsflyIn', [
            transition('void => *', [
                style({ transform: 'translateX(500)' }),
                animate('500ms 400ms ease-in', style({ transform: 'translateX(0)' }))
            ]),
        ]),
    ]
...
export class HomeComponent implements OnInit, AfterViewInit {
    startLoadAnimations = false;
...
    ngAfterViewInit(): void {
        setTimeout(() => {
            this.startLoadAnimations = true;
        }, 10);
    }
...

@rynop You are right. For me, it didn't work in some cases. I can't figure out what is going on.

While I'm not crazy about it, I "think" I have a workaround. Would be grateful if you could test on your side @vahidvdn and see if it works for you. In short I don't use void or *, manually set state and manually change state after a timeout in ngAfterViewInit().

            <FlexboxLayout height="54" flexDirection="row" justifyContent="flex-start" alignItems="stretch"
                flexWrap="nowrap">
                <GridLayout [@test]="startLoadAnimations?'in':'init'" *ngFor="let club of byClub; let i = index"
                    height="54" class="small-card round-border" [background]="club.background">
                    <Image horizontalAlignment="center" verticalAlignment="center" [src]="club.src">
                    </Image>
                </GridLayout>
            </FlexboxLayout>
...
    animations: [       
trigger('test', [
            state('init', style({
                opacity: 0,
                transform: 'translateX(500)'
            })),
            state('in', style({
                opacity: 1,
                transform: 'translateX(0)'
            })),
            transition('init => in', [
                animate('1s ease-in')
            ]),
        ])
    ]
...
export class HomeComponent implements OnInit, AfterViewInit {
    startLoadAnimations = false;
...
    ngAfterViewInit(): void {
        setTimeout(() => {
            this.startLoadAnimations = true;
        }, 500);
    }
...

Def not ideal, but I think its working..

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Onkarn92 picture Onkarn92  路  24Comments

ignaciofuentes picture ignaciofuentes  路  31Comments

codeback picture codeback  路  34Comments

hamorphis picture hamorphis  路  38Comments

tsonevn picture tsonevn  路  27Comments