3

I am making an angular2 application. My biggest problem is the inability to defer loading of main component's dependent child component till some promise gets resolved.

I have app.component.ts, with class named AppComponent, which I bootstrap in boot.ts like this:

bootstrap(AppComponent, [ROUTER_PROVIDERS, HTTP_PROVIDERS]);

Now I want to call few very vital http services before navigating to my default route, i.e-'/'. One http service returns data to me that will be used for doing SEO and setting meta data on various routes.

I know that the constructor of any class is called at first, but I don't know if the constructor waits for the promises to get resolved.

Vineet 'DEVIN' Dev
  • 1,183
  • 1
  • 10
  • 35

3 Answers3

0

If you use the Router you can use CanActivate otherwise just wrap the template with an *ngIf="dataArrived"

See also How to pass parameters rendered from backend to angular2 bootstrap method

Community
  • 1
  • 1
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • So there's no way to defer the loading of child components? I am not sure with *ngIf because I think DomContentLoaded will be done as soon as I go to the route and thus changing meta tags after "dataArrived" won't do any good to SEO related tags like title and description. – Vineet 'DEVIN' Dev Apr 28 '16 at 08:16
  • I'm not sure I understand your comment. Why do you think it does matter if meta tags are set before or after a route was activated or why and how `*ngIf` and `DomContentLoaded` are related. – Günter Zöchbauer Apr 28 '16 at 08:22
  • Google bots crawl the page after Dom Content is loaded for a particular push state. And I think that *ngIf is not related to DomContentLoaded, thats why I am worried if using *ngIf would not solve my problem. – Vineet 'DEVIN' Dev Apr 28 '16 at 08:26
  • So you want to delay the initial router navigation until the data arrived from the server? – Günter Zöchbauer Apr 28 '16 at 08:28
  • Yes. Say that I have routes /, /a, /b. User can go to - mydoamin.com/ or mydomain/a or mydomain/b. I have to set meta tags in every case. So I want to get the meta tag details from server(which changes dynamically for some reasons) and then set them for the route. – Vineet 'DEVIN' Dev Apr 28 '16 at 08:33
  • I think `CanActivate` is what you want. When it returns a promise Angular should wait until the promise has resolved. There is currently a bug AFAIR that the router adds the component immediately anyway but only updates the URL when the promise completes (could be the other way around) but that's how it is supposed to work and a pull request for a fix of this issue does already exist. – Günter Zöchbauer Apr 28 '16 at 08:37
  • Can I inject and use my service into @CanActivate? – Vineet 'DEVIN' Dev Apr 28 '16 at 09:05
  • That's a bit limited currently. See https://github.com/angular/angular/issues/4112#issuecomment-153811572 for a workaround. But a new router that addresses this limitation is work-in-progress. – Günter Zöchbauer Apr 28 '16 at 09:09
0

You could bootstrap asynchronously after your request(s) complete(s). Here is a sample:

var app = platform(BROWSER_PROVIDERS)
   .application([BROWSER_APP_PROVIDERS, appProviders]);

var service = app.injector.get(CompaniesService);

service.executeSomething().flatMap((data) => {
  var companiesProvider = new Provider('data', { useValue: data });
  return app.bootstrap(appComponentType, [ companiesProvider ]);
}).toPromise();

See this question for more details:

and the corresponding plunkr: https://plnkr.co/edit/ooMNzEw2ptWrumwAX5zP?p=preview.

Community
  • 1
  • 1
Thierry Templier
  • 198,364
  • 44
  • 396
  • 360
0

another solution is using a timer in the constructor:

setTimeout(() => {
    call your function here
}, 500); 
sa_
  • 2,854
  • 3
  • 22
  • 29