Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 animate parent and child components at the same time

I've written plunk to illustrate my issue: LINK

I need to animate parent component, and at the same time I want to make some animation in child component. It seems that angular is blocking animation on child component, and then simply jumps states after parent animation ends without any transition.

Is there any way to make animations work in parallel, or at least chain without using callbacks?

@Component({
  selector: 'outer',
  template: `
    <div [@state]="state" (mouseenter)="state='wide'" (mouseleave)="state='narrow'" style="background-color: red;">
      <inner [stateInner]="state"></inner>
    </div>`,
  animations:[
    trigger('state', [
      state('narrow', style({
        width: '100px'
      })),
      state('wide', style({
        width: '400px'
      })),
      transition('* => *', animate('500ms'))
    ])  
  ]
})
export class Outer {
  public state: string = 'narrow';
  constructor() {
  }
}


@Component({
  selector: 'inner',
  template: `
    <div [@stateInner]="stateInner">
      <h2>Hello</h2>
    </div>`,
  animations:[
    trigger('stateInner', [
      state('narrow', style({
        height: '100px'
      })),
      state('wide', style({
        height: '400px'
      })),
      transition('* => *', animate('500ms'))
    ])  
  ]
})
export class Inner {
  @Input() stateInner: string = 'narrow';
  constructor() {
  }
}
like image 991
K. Kowalczyk Avatar asked Sep 12 '17 13:09

K. Kowalczyk


Video Answer


2 Answers

I'd like to say that using callbacks is the best way to handle this for future code, but if you just need to get this to work the trick is to use OnChanges, SimpleChanges, and a setTimeout().

Working Plunker to show how it works, as well as the inner div main changes in code:

imports

import {Component, Input, OnChanges, SimpleChanges} from '@angular/core'

template

  template: `
    <div [@stateInner]="localChange">
      <h2>Hello</h2>
    </div>

class export

  localChange = 'narrow';

  ngOnChanges( changes: SimpleChanges ) {
    console.log(changes)
    setTimeout( () => this.localChange = changes.stateInner.currentValue, 500);
  }
like image 115
Z. Bagley Avatar answered Oct 20 '22 10:10

Z. Bagley


You can run parent and child animations at the same time without events and timeouts, animateChild() can help us. Here is the parent animations description:

animations: [
    trigger('state', [
        state('narrow', style({
            width: '100px'
        })),
        state('wide', style({
            width: '400px'
        })),
        transition('narrow => wide', [
            style({
                width: '100px'
            }),
            group([
                animate('500ms', style({
                    width: '400px'
                })),
                query('@stateInner', [
                    animateChild()
                ])
            ])
        ]),
        transition('wide => narrow', [
            style({
                width: '400px'
            }),
            group([
                animate('500ms', style({
                    width: '100px'
                })),
                query('@stateInner', [
                    animateChild()
                ])
            ])
        ])
    ])
]

group() - runs multiple animations in parallel, here is an example from the documentation

query() - finds child animations

animateChild() - executes child animations

The drawback of this solution, as you may notice, I described forward and backward parent transitions and styles separately, otherwise the parent state isn't animated correctly for some reason. Here is my question about the problem.

like image 43
Valeriy Katkov Avatar answered Oct 20 '22 10:10

Valeriy Katkov