9

I want to show and hide my modal component with Angular2 animations. At the moment this is my code:

animations: [
    trigger('modalState', [
      state('true', style({
        display: 'block',
        opacity: '1'
      })),
      state('false',   style({
        display: 'none',
        opacity: '0'
      })),
      transition('* => *', animate('200ms ease'))
    ])
  ]

The problem: At the moment the display block is set after 200ms. So you can't see the animated opacity. The display should be set directly after event.

How to do this?

rakete
  • 2,953
  • 11
  • 54
  • 108

4 Answers4

6

You can use animation hooks for discrete CSS properties such as display. So, your animation would include only the opacity:

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

And then in your template you can use animation start/end hooks to toggle the display:

<div
  [@modalState]="isShown"
  (@modalState.start)="$event.element.style.display = 'block'"
  (@modalState.done)="$event.element.style.display = ($event.toState ? 'block' : 'none')">
  ...
</div>

Assuming isShown is Boolean.

Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Lev Himmelfarb
  • 113
  • 1
  • 5
4

You can use 2 different triggers for the same element.

The first one will handle the 'opacity' and the second one will handle the 'display' property. So use duration and delay time to get what you need.

animations: [
    trigger('modalStateOpacity', [
      state('true',  style({ opacity: '1' })),
      state('false', style({ opacity: '0' })),
      transition('0 <=> 1', animate('200ms ease'))
    ]),
    trigger('modalStateDisplay', [
      state('true',  style({ display: 'block' })),
      state('false', style({ display: 'none'  })),
      transition('0 => 1', animate('0ms ease')),
      transition('1 => 0', animate('0ms 200ms ease'))
    ])
  ]
Alexander Paul
  • 423
  • 1
  • 6
  • 11
  • 1
    The concept is great, but I can't get it to apply the display:none property – Logus Graphics Nov 30 '17 at 16:06
  • 1
    I've tried to use display on Chrome and it works, but you also can try with "zIndex" to move the undesired tag behind all the other. `style({ zIndex: 100 })` for true state and `style({ zIndex: 0 })` for false state – Alexander Paul Dec 06 '17 at 09:56
1

You were just near. You have to set style to display:'block' to see the animation, at least at the beginning of the transition from state false to true

trigger('showOrHide', [
   state('true', style({ opacity: 1, display: 'block' })),
   state('false', style({ opacity: 0, display: 'none' })),
   transition('0 <=> 1', [
      style({ display: 'block' }), 
      animate('200ms ease')
   ]),
]),
TCH
  • 421
  • 1
  • 6
  • 25
1

I was able to get something similar to work (I'm using Angular 7) using the "sequence" method.

@Component({
  selector: "app-keller-edit-audit",
  templateUrl: "./keller-edit-audit.component.html",
  styleUrls: ["./keller-edit-audit.component.less"],
  animations: [
    trigger("panelDoHideTrigger", [
      // The final state of things if panel is hidden
      state("true", style({ opacity: 0, display: "none" })),
      // The final state of things if the panel is not hidden
      state("false", style({ opacity: 1, display: "block" })),
      // SHOW the panel
      transition("true => false", [
        // Use sequence to make steps go sequential
        sequence(
          [
            // First flip the display to block so we can see the opacity fade in
            style({ display: "block", opacity: 0.1 }),
            // Now fade in using opacity
            animate(500, style({ opacity: 1 }))
          ]
        ),
      ]),
      // HIDE the panel
      transition("false => true", [
        animate(500, style({ opacity: 0 })),
      ]),
    ]),
  ],
})
...
...
...
<div class="col-xs-2">
   <span *ngIf="ccg.DoHideDetail=='true'">
      <a style="cursor:pointer" (click)="ccg.DoHideDetail='false'">Show Details</a>
   </span>
   <span *ngIf="ccg.DoHideDetail=='false'">
       <a style="cursor:pointer" (click)="ccg.DoHideDetail='true'">Hide Details</a>
   </span>
</div>

<div [@panelDoHideTrigger]="ccg.DoHideDetail" >
    <ng-container *ngFor="let cc of ccg.AuditCycleCounts; let i2=index">