Angular 2 : Displaying resolver dependent child components asynchronously

I have three children components nested in a parent component. I am trying to have these to display independently, once they resolve their data. So far the complete route is only activated when all the resolves have fetched their data, which results in all children components appearing at once after quite some time (some API calls being long).

Here is some simplified code :

Routes :

const appRoutes: Routes = [
  {
    path: '',
    redirectTo: 'home',
    pathMatch: 'full'
  },
  {
    path: 'home',
    component: HomeComponent,
    children : [
      {
        path: 'cpt1',
        component: Component1,
        outlet: 'cpt1',
        resolve: {
          data: Cpt1Resolve
        }
      },
      {
        path: 'cpt2',
        component: Component2,
        outlet: 'cpt2',
        resolve: {
          data: Cpt2Resolve
        }
      },
      {
        path: 'cpt3',
        component: Component3,
        outlet: 'cpt3',
        resolve: {
          data: Cpt3Resolve
        }
      }
    ]
  }
];

App component :

@Component({
  selector: 'my-app',
  template: `
      <h1>Angular 2 Asynchronous loading of children components</h1>
      <div>
        <router-outlet></router-outlet>
      </div>`
})
export class AppComponent {}

Home component :

@Component({
  selector: 'home-cpt',
  template: `
  <h2>You're on home</h2>
  <router-outlet></router-outlet>
  <router-outlet name="cpt1"></router-outlet>
  <router-outlet name="cpt2"></router-outlet>
  <router-outlet name="cpt3"></router-outlet>
  `
})

export class HomeComponent {
   constructor(router: Router) {
    router.navigateByUrl('home/(cpt1:cpt1//cpt2:cpt2//cpt3:cpt3)');
  }
}

And finally a child component and it's resolve :

// CHILD COMPONENT 1

@Component({
  selector: 'cpt1',
  template: `
  <h3>Cpt1 displayed</h3>
  `
})

export class Component1 implements OnInit {

  constructor(
    private route: ActivatedRoute,
    private router: Router
  ) { }

  ngOnInit(): void {
    this.route.data.forEach((data: any) => {   
      console.log('data cpt 1', data);
    });
  }

}

@Injectable()
export class Cpt1Resolve implements Resolve<any> {
    constructor() {}
        resolve (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<any> {
            return Observable.create((observer) => {
                  setTimeout(() => { 
                    observer.next('Sample Text 1');
                    observer.complete();
                  }, 2000);
            });
     }
}

Is there a way to force the router to display children components as soon as they receive data ? What am I doing wrong here ?

The complete plunker (wait for it)

Upvotes: 0

Views: 1036

Answers (1)

Riva Madan
Riva Madan

Reputation: 98

Seems that unfortunately displaying a component as soon as the resolver is complete is not possible at the moment and the angular people don't plan on changing it to make it possible.

https://github.com/angular/angular/issues/14064

Upvotes: 2

Related Questions