6

I have an animation that's supposed to slide in and slide out when I switch between components, but it's not working. So when you switch from component the one you see right now should slide to the left, while the one you want to load comes sliding from the right.

Excuse my terrible drawing but I hope this makes more sense: enter image description here

This is my code:

checklist.component.ts

import {Component, Input, OnInit, ViewChild, ViewEncapsulation} from '@angular/core';
import {animate, style, transition, trigger} from "@angular/animations";

@Component({
    selector: 'app-checklist',
    templateUrl: './checklist.component.html',
    styleUrls: ['./checklist.component.scss'],
    encapsulation: ViewEncapsulation.None,
    animations: [
        trigger('animation', [
            transition('void => *', [
                style({transform: 'translateX(-100%)'}),
                animate(1000)
            ]),
            transition('* => void', [
                animate(1000,
                    style({transform: 'translateX(100%)'}))
            ]),
        ])
    ]
})
export class ChecklistComponent implements OnInit {

    @Input() page = 'main';

    @ViewChild('modalElement') modalElement;

    constructor() {
    }

    ngOnInit() {
    }

    onPage(page: string): void {
        this.page = page;
    }
}

checklist.component.html

<ng-template #modalElement let-c="close" let-d="dismiss">
    <div class="modal-container">
        <div class="modal-header">
            <h4 class="modal-title">{{ 'Checklist'| translate }}</h4>
            <button type="button" class="close" aria-label="Close" (click)="d('Cross click')">
                <span aria-hidden="true">&times;</span>
            </button>
        </div>
        <div class="modal-body" id="modal-body">
            <app-checklist-main *ngIf="page == 'main'" [@animation] (page)="onPage($event)"></app-checklist-main>
            <app-checklist-view *ngIf="page == 'view'" [@animation]></app-checklist-view>
            <app-checklist-mutate *ngIf="page == 'mutate'" [@animation]></app-checklist-mutate>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-default" (click)="c('Close click')">{{ 'Close'| translate }}</button>
            <button type="button" class="btn btn-primary" (click)="onConfirm($event)">{{ 'Confirm'| translate }}
            </button>
        </div>
    </div>
</ng-template>

Anyone got any idea why it's not working??

EDIT:

Example: https://stackblitz.com/edit/angular-enethh

2 Answers 2

16

I have found that animations do not fire correctly on component tags that are not displayed as block. Update your template to the following and you should see your animations run:

<div class="modal-body" id="modal-body">
  <app-checklist-main style="display: block" *ngIf="page == 'main'" [@animation] (page)="onPage($event)"></app-checklist-main>
  <app-checklist-view style="display: block" *ngIf="page == 'view'" [@animation]></app-checklist-view>
  <app-checklist-mutate style="display: block" *ngIf="page == 'mutate'" [@animation]></app-checklist-mutate>
</div>

This is because the component is displayed as inline by default and according to the Spec animations do not run on those elements.

Sign up to request clarification or add additional context in comments.

2 Comments

What if the element according to the design spec has alternate between display: flex and display: none; is there any hack?
@sudo_kaizen I think the hack would be to have the element do display: none as an *ngIf and then the first tag inside the element should have display: flex
7
  1. Your transitions have placeholders :

     'void => *' => ':enter'
     '* => void' => ':leave'
    
  2. You don't have states in your animations. If you don't have states, you can't use transitions.

  3. You can remove the braces of your animation attributes :

      [@animation] => @animation
    
  4. You current "animation" is just a change of style

  5. I will use opacity instead of transform so that you can see the animation, because with your animation and without knowing your page layout, I'm not sure you will see it otherwise.

  6. I will use a cubic bezier function because I like it.

So here is a correct animation :

trigger('animation', [
  state('void', style({ opacity: 0, })),
  state('*', style({ opacity: 1, })),
  transition(':enter', animate(`1000ms ease-out`)),
  transition(':leave', animate(`1000ms ease-in`))
])

Now you can test that, and replace opacity and get rid of the cubic bezier function (if you want to).

10 Comments

Thanks for your answer, but sadly it does not work. It's just as before, it does wait the 1000ms, but no animation...
Well... I don't think I can. This is part of a bigger project and it uses a lot of custom middlewares, components etc. to work. A lot of it is confidential, so to make this work in an example would take me hours up on hours to strip everything down and to make it work in an example envoirment. What I can do is make demo video's or screenshots. I can also provide more code if you need.
That's why it called a minimal & verifiable example :D You only create a component with the same style and the same layout, then you put a button that changes your ngIf condition. And I can't see images (corporate proxy), and we will have a hard time if you don't provide me something that I can play with ...
Okay, I will do my best. Hang on.
I have added an example to my question.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.