Pre-load component data before rendering

Hi everybody! I’m facing a challenge trying to accomplish this. I have a component which is being rendered with a selector. My problem is that this component make some heavy async work on ngOnInit(). This leads to a malfunction of my application in poor internet environments.

The thing is, my selector of the component is wrapped around a ngIf, but if I don’t put the selector on the html the component is not being instantiated and no data is retrieved. And if I put the selector in the html the component is rendered before data is available.

I have tried some solutions but none work for me.

Show I be able to make new myProblematicComponent() and send an event from the component when the data is loaded? But if I do this, how I render the component in my view? I suppose if I just push the selector in the view other data is being fetched instead the first one.

Maybe I am not explaining very well.

Thank you

1 Like

Why do you put your hard logic inside the controller? Just put it in servers, then you can call it before and use the recieved data.

I’m afraid that’s not a solution. Also, I have never said the hard logic relies on fetching data from a server. In fact, it mostly relies on operations I do on a local SQLite.

Maybe I don’t understand your problem. If you have a delay, you can show spinner or any text, like “Loading…”. If you want to preload data, you must use a service and call it before. Not hard, just choose your way.

Yeah I think I didn’t explain myself quite good.

One focused question could be, how do you preload data and render it with a component selector? For example, imagine this:

<div *ngIf="isDataAvailable">
  <custom-card></custom-card>
</div>

Custom-card is the selector for my problematic component. If I load the data, and then set:
this.isDataAvailable = true

Then, once <custom-card></custom-card> is instantiated in my view it does not have the data available from the component.

On the other hand, if I delegate the data loading in my component ngOnInit() (for example), then the data is available to the component but I have timing problems in poor network environments due to the time it takes to load the data.

Is it more clear now?

2 Likes

There’s a few things you can do:

  1. Use a service for getting the data before showing the custom-card component, then retrieve the data inside the component.
  2. Change *ngIf for [hidden] so that the component does exists but it isn’t shown, then you can retrieve the data from the constructor or ngOnInit() method.

My recommendation is 1, you should use a service to separate controller logic from model, that also allows for retrieving the data from any part of the app (including the parent component) to then showing the child and in it showing the gathered data.

luchillo17 hello! As you state, I’m retrieving the data from a service. That’s not the problem.

Page view -> Component -> data service

I like the solution 2! I have not though about it but I’m gonna try it. I think it could fit my problem. I will update when I have an answer.

Thank you!!

If retrieving the data from a service is not your issue then what is it? can’t call the gather data method from the parent?

If you call the component from a HTML selector this is the flow:

<custom-selector></custom-selector> -> component ngOnInit call to service -> wait -> component HTML is rendered into the parent view without data -> wait -> wait -> data is available and rendered into the view

If you retrieve the data and wait until it is finished, how then you render into the view using custom-selector?

To clarify custom-selector is the child?

If you retrieve the data in the parent before showing the child, you only need the service to be in the parent providers array, that way it will be available to both so you can ask the service to gather data from the parent, then when data is available show the child and in child retrieve the data from service, which is provided by the parent.

Hi again!! Yes custom-selector is the child. Just a component, not a “page”.

That way of calling the service from the page, instead of in the component is not the anti-pattern of components? I mean, it is supposed a component should be reusable and self-contained (of course if we don’t take in mind the service). Am I wrong and the data should be retrieved from the “page” (the parent)?

Thank you!

It should be reusable and self-contained, but since you need the data to be available before rendering, pre-fetching with the parent isn’t wrong, just use the service in both, call the gather logic in parent and in child just ask if content is already fetched, if not fetch, but if it does just use it.

That way the component is self contained, you just tell the parent to ask the server to fetch ahead of time the data of the children.