2017-12-16 2 views
1

Ich versuche einige Routenänderungen in Angular zu animieren. Die Animation sollte in der Höhe zwischen nichts und der Höhe des Inhalts animieren. Dies funktioniert sehr gut, wenn der Inhalt im Voraus bekannt ist, siehe diese Plunkr: http://plnkr.co/edit/FOZSZOJaSpLbrs2vl6KaWie man angulare Animationen auf das Rendering warten lässt

Es funktioniert jedoch nicht sehr gut, in dem Moment, eine HTTP-Anfrage muss passieren. Siehe dieses plunkr: http://plnkr.co/edit/vyobBtb5KDO7nkYLLsto (Hier wurde die HTTP-Anfrage mit einem verzögerten RX-Vorgang simuliert)

Ich wäre völlig in Ordnung mit der Animation nicht gestartet, bis Inhalt geladen wurde, aber ich bezweifle, dass das möglich ist.

Was ich vermute, ist falsch, ist, dass Angular misst die Höhe der "twoComponent" rechts, wenn es eingefügt wird, aber bevor es fertig geladen hat, was dann dies verursacht.

Insgesamt nicht richtig funktioniert Code:

//our root app component 
import {Component, NgModule, VERSION} from '@angular/core' 
import {BrowserModule} from '@angular/platform-browser' 
import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; 
import {RouterModule, Routes} from '@angular/router'; 
import {HashLocationStrategy} from '@angular/common'; 
import {animate, animateChild, query, style, transition, trigger} from '@angular/animations'; 
import {Observable} from 'rxjs/Observable'; 
import {of} from 'rxjs/observable/of'; 
import 'rxjs/add/operator/delay'; 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <h2>Hello {{name}}</h2> 
     <a routerLink="">Go to one</a> 
     <a routerLink="two">Go to two</a> 
     <div [@routeAnimations]="prepareRoute(outlet)" 
      style="background-color:pink" 
      id="main-router-outlet"> 
     <router-outlet #outlet="outlet"></router-outlet> 
     </div> 
    </div> 
    `, 
    animations: [ 
    trigger('routeAnimations', [ 
     transition('* => *', [ 
     query(':enter', [ 
      style({height: 0, opacity: 0, width: 0}), 
     ], {optional: true}), 
     query(':leave', [ 
      style({height: '*', width: '*'}), 
      animate('200ms', style({opacity: 0})), 
      animate('500ms', style({height: 0, width: 0})), 
     ], {optional: true}), 
     query(':enter', [ 
      animate('500ms', style({height: '*', width: '*'})), 
      animate('500ms', style({opacity: 1})), 
      animateChild(), 
     ], {optional: true}), 
     ]), 
    ]), 
    ], 
    styles: [ 
    `#main-router-outlet ::ng-deep > * { 
     display: block; 
     } ` 
    ] 
}) 
export class App { 
    name:string; 
    constructor() { 
    this.name = `Angular! v${VERSION.full}` 
    } 

    public prepareRoute(outlet: RouterOutlet) { 
    return outlet.activatedRouteData['animation'] || ''; 
    } 
} 

@Component({ 
    template: `one component<br>more` 
}) 
export class oneComponent { 

} 


@Component({ 
    template: `two component 
    <div *ngFor="let s of dynamicContent|async"> 
    {{s}} 
    </div> 
    ` 
}) 
export class twoComponent { 
    public dynamicContent: Observable<string[]>; 

    ngOnInit() { 
    this.dynamicContent = of(['foo', 'bar', 'baz']) 
     .delay(200); 
    } 
} 

@NgModule({ 
    imports: [ 
    BrowserModule, 
    BrowserAnimationsModule, 
    RouterModule.forRoot([{ 
     path: '', 
     component: oneComponent, 
    data: { 
     animation: 'one', 
    } 
    }, 
    { 
     path: 'two', 
     component: twoComponent, 
    data: { 
     animation: 'two', 
    } 
    }], { useClass: HashLocationStrategy }) 
    ], 
    declarations: [ App, oneComponent, twoComponent ], 
    bootstrap: [ App ] 
}) 
export class AppModule {} 
+2

Sie einen Resolver auf die Route hinzufügen könnte, die den Inhalt lädt, bevor die Routenänderung geschieht: https://angular.io/api/router/Resolve –

Antwort

1

Verwenden Sie einen Resolver: Demo

Resolver

import { Injectable } from '@angular/core'; 
import { Resolve, ActivatedRouteSnapshot,ActivatedRoute } from '@angular/router'; 
import { ContactsService } from './contacts.service'; 

@Injectable() 
export class ArrResolve implements Resolve<string[]> { 

    constructor() {} 

    resolve(route: ActivatedRouteSnapshot) { 
    return of(['foo', 'bar', 'baz']) 
     .delay(200); 
    } 
} 

AppModule

@NgModule({ 
    imports: [ 
    BrowserModule, 
    BrowserAnimationsModule, 
    RouterModule.forRoot([{ 
     path: '', 
     component: oneComponent, 
    data: { 
     animation: 'one', 
    } 
    }, 
    { 
     path: 'two', 
     component: twoComponent, 
    data: { 
     animation: 'two', 
    }, 
    resolve: { 
     arr: ArrResolve 
    } 
    }], { useClass: HashLocationStrategy }) 
    ], 
    declarations: [ App, oneComponent, twoComponent ], 
    bootstrap: [ App ], 
    providers: [ArrResolve] 
}) 
export class AppModule {} 

Zwei-Komponenten-

@Component({ 
    template: `two component 
    <div *ngFor="let s of dynamicContent|async"> 
    {{s}} 
    </div> 
    ` 
}) 
export class twoComponent { 
    public dynamicContent: Observable<string[]>; 
    constructor(private route:ActivatedRoute) { 

    } 

    ngOnInit() { 
    this.dynamicContent = of(this.route.snapshot.data.arr); 
    } 
} 
Verwandte Themen