Rohit
Rohit

Reputation: 3156

Animation with initial/after state

I'm trying to sort through how to do an Angular animation with an initial state. I'm trying to develop a slide up/down animation, so far with:

trigger(
    'slideHeight',
    [
        state('closed', style({
            display: 'none',
            height: 0
        })),
        state('open', style({
            // display: 'block',
            height: '*'
        })),
        transition('* <=> *', [
            style({
                display: 'block'
            }),
            animate('.5s ease')
        ])
    ]
)

In the jQuery version, the element in question has display: none on it, and I notice that jQuery slides open, and then I see display: block on the final element.

When I have display: 'block' commented out as above, it works as expected, however, when the page loads, it starts with the elements going from full height to none (which makes sense I guess?), which is weird for the user.

I'm trying to figure out how I can set it up so when closed, first it goes to display: block, runs the height animation, and holds block. In the other direction, I want to have block until it's done, adding a display: none.

I've tried adding a class with display none, but as animations don't add a class before/after, it didn't quite work as expected. I suspect this should be a combination of the Angular animation JS and CSS classes, but I can't quite figure out the pattern. Any advice in how to address this would be great.

Upvotes: 2

Views: 8541

Answers (2)

Simon_Weaver
Simon_Weaver

Reputation: 146150

Not sure if this is exactly what you want, but you can use * to describe a state which is the 'default' state. I see you're already doing this with height but you can define a state as * too.

I want to be able to show and hide an arrow. So it has two logical states 'in' and 'out'. That's easy enough switching between the two. But if the initial state should be 'in' then I want it to fade in, but there won't be a 'starting point' for the out => in animation or even * => in unless you define a * state.

 animations: [
    trigger('showArrow',
    [            
        state('*', style({opacity: 0})),
        state('in', style({opacity: 1})),
        state('out', style({opacity: 0})),

        transition('* => in', [
           animate(15000)    
        ]),

        transition('* => out', [
            animate(200)
        ])
    ])
  ],

So my icon is defined like this (note that this is a custom svg):

<mat-icon [@showArrow]="(showArrow$ | async) ? 'in' : 'out'"
          svgIcon="right-arrow"></mat-icon>

Even if the initial state is hardcoded to true (so there is no state change as such) it will still fade in because I've defined a * starting state (with 0 opacity).

    this.showArrow$ = new BehaviorSubject(true);

Upvotes: 4

Lucas
Lucas

Reputation: 10313

I think you need two transitions to get what you want.

trigger(
    'slideHeight',
    [
        state('closed', style({
            display: 'none',
            height: 0
        })),
        state('open', style({
            height: '*'
        })),
        transition('closed => open', [style({ display: none }), animate('.5s ease')]),
        transition('open => closed', [style({ display: 'block' }), animate('.5s ease')])
    ]
)

Upvotes: 4

Related Questions