Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular animations failing for opacity settings (and more bugs)

I've got a card component that wraps another different components inside. It's like a wrapper component for making the UI fancy; I guess you have seen this approach many times.

Thing is, I want these cards to be hideable, just showing the footer (which, by the way, is also created by the child component, not the card itself).

Therefore, my approach to handle animations, is:

  1. I click in the icon that switches the card between visible and hidden.
  2. It outputs (with @Output()) some variable that is used in the child element for hiding the part of the component you only want to show when the card is "activated".
  3. This same variable is used in two different animations: one in the card, for making it smaller, and other in the inner component, for hiding the part that you don't want to show when the card is "deactivated".

You can see the big picture with these little snippets, starting by the implementation:

<card [title]="'DATE SELECT'" class="col" (cardOpen)="config?.cardStatus['dateselect'] = $event">
   <date-picker-wrapper class="date-wrapper" [cardOpen]="config?.cardStatus['dateselect']" [config]="config" [dateranges]="dateranges" [doubleDateRange]="false">
   </date-picker-wrapper>
</card>

Inner component:

<div class="row margin upper-margin" [@animate]="cardOpen">
    // lots of code
</div>

Parent component (card):

@Component({
    selector: "card",
    styleUrls: ["./card.css"],
    template: `
    <div class="col card" [@animate]="enabled">
      <div class="row card-header">
        {{title}}
        <i (click)="switchVisibility()" class="fa fa-chevron-down icon-right"></i>
      </div>
      <ng-content></ng-content>

    </div>
    `,
    animations: [
      trigger('animate', [
        state('false', style({
          minHeight: "98px",
          height: "98px",
          maxHeight: "98px",

        })),
        state('true', style({
          minHeight: "270px",
          height: "270px",
          maxHeight: "270px"
        })),
        transition('false => true', animate('400ms ease-in')),
        transition('true => false', animate('400ms ease-out'))
      ])
    ]
})

Okay, this approach "works". See the gifs and judge by yourself:

Behavior with "normal" clicks: https://gyazo.com/2c24d457797de947e907eed8a7ec432e

Strange bug when clicking fast (one out of various different ones that appear in this situation): https://gyazo.com/bdc8dde3b24b712fa2b5f4dd530970dc

Okay, this is weird. Look at how my code is in the inner component to hide the part I don't want to show:

animations: [
  trigger('animate', [
    state('false', style({
      opacity: 0
    })),
    state('true', style({
      opacity: 1
    })),
    transition('false => true', animate('100ms')),
    transition('true => false', animate('100ms'))
  ])
]

I tried putting in the transition, the "ease in", "ease out", aswell the "fade" options, but nothing seems to change the behavior. Not even changing the duration. None of these changes avoid these bugs from happening, and absolutely, no one makes it do what I want: make that part of the component appear slowly, so the opacity grows/lowers down slowly from one state to the another, instead of suddenly appearing/disappearing.

like image 269
Zerok Avatar asked Apr 13 '18 15:04

Zerok


1 Answers

If you work with a component that change its visibility, you have to work with two transition alias:

  • :enter that is equivalent to void => * transition state.
  • :leave that is equivalent to * => void transition state.

You can read official documentation here or watch on youtube.

like image 64
xcesco Avatar answered Nov 12 '22 04:11

xcesco