Search code examples
javascriptangularangular-ui-routerangular-routerangular-animations

How can I query for :enter and :leave of a UI-VIEW for animation in Angular 4 using a trigger that wraps the entire UI-VIEW directive


So in Angular 4.2+ there is a new Query animation function that allows you to Query for various things (:enter, :leave, class names, elements, etc) and you can apply animations to them. The KEY concept that I am trying to solve is that you are WRAPPING the router-outlet with a trigger and then that trigger has knowledge of both the :enter and :leave of BOTH views that are animating. This is ESSENTIAL in the question and answer I am seeking. If you put the trigger INSIDE a view (hostbinding) you are only able to trigger for that specific UI-VIEW / Router Outlet. By putting it on the OUTSIDE of the UI-VIEW / Angular-Router-Outlet you are able to control both the in and the out of both views.

Here is a WORKING StackBlitz of Angular with the built in router working. https://stackblitz.com/edit/ng-router-fade-transitions

This is using ANGULAR 4's built in router @angular/router which has no problem finding the :enter and the :leave of the router outlet

This is the stackblitz that I need the ANSWER To...

https://stackblitz.com/edit/ui-router-transitions

If you open the console log you can see that when I transition from Hello -> World I am able to perform a animation, I turned off 'optional' because you need it off so you can see the errors, if you turn it on then the errors just fail silently (the error is below). It's imperative that the trigger remains wrapping the UI-VIEW outlet somehow so any help would be much appreciated.

errors.ts:42 ERROR Error: Unable to process animations due to the following failed trigger transitions
@fadeAnimation has failed due to:

- `query(":enter")` returned zero elements. (Use `query(":enter", { optional: true })` if you wish to allow this.)

Solution

  • UIRouter 1.0.0-rc.0 has been released and this is baked into UIRouter now.

    to query for animations you would do something like this:

            <div [@uiAnimation]="getStatus(mainState)">
                <ui-view #mainState></ui-view>
            </div>
    

    and the corresponding Typescript in your component:

    private lastState = null;
    
    public getStatus(uiview) {
         const state = uiview.state.name;
         if (state !== this.lastState) {
              this.lastState = state;
         }
         return `${state.replace('app.', '' )}`;
    }
    

    then in your animation code you can trigger a transition (prevstate => newstate)

    prevstate / newstate would be the state name that is returned from getStatus()