Reputation: 107
I have template code like this:
<li *ngIf="isRoot() || isSoftware()">
Also i have this functions in my components code:
isRoot() {
return this.service.Level == 'Root';
}
isSoftwareOnly() {
return this.service.ServiceType == 'Software';
}
this.service gets by HTTP request.
How can I get request before template starts render? Now isRoot()
and isSoftware()
always return false, because this.service.Level and this.service.ServiceType are undefined
Upvotes: 3
Views: 1851
Reputation: 7221
If you have to check before a component initialization, the best way to perform that is Guards mechanism (guide here). To create a guard just create a class implementing CanActivate interface. The canActivate method of your class should return an Observable that tells the router if it can load a route.
So your guard will ensure your GET XHR have returned before activating the route containing your component.
something like ( view doc here )
@Injectable()
class CanActivateCheckServiceState implements CanActivate {
constructor(private myService: <YourService>) {}
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
): Observable<boolean>|Promise<boolean>|boolean {
return this.myService.<yourGetMethod>
.map(() => return true)
.catch(() => return false)
}
}
Then use it in your routing config:
@NgModule({
imports: [
RouterModule.forRoot([
{
path: '<yourPath>',
component: <yourComponent>,
canActivate: [CanActivateCheckServiceState]
}
])
],
providers: [CanActivateCheckServiceState, <yourService>]
})
class YourModule {}
Upvotes: 1
Reputation: 12350
I see three ways:
First (quickest): Use constructor
of your component (let's say that you have fetchData
method in your service to make an http request:
export class Component {
constructor(private service: MyService) {
this.service.fetchData();
}
}
Second (slower): Use ngOnInit
hook - data will be fetched in the same moment when initialization of view starts.
Third: Use ngOnChanges
lifecycle hook (in my opinion this is not best practice in your usecase) - according to documentation:
Respond when Angular (re)sets data-bound input properties. The method receives a SimpleChanges object of current and previous property values. Called before ngOnInit() and whenever one or more data-bound input properties change.
More about lifecycle hooks in Angular.
Upvotes: 1
Reputation: 2454
You can wrap you entire template in an ng-container and have a flag in your component that is set to true once the data has loaded:
export class MyComponent {
dataHasLoaded: boolean = false;
ngOnInit() {
this.loadData();
}
loadData() {
// send http-request
this.httpService.getData().subscribe(() => {
this.dataHasLoaded = true;
})
In your template:
<ng-container *ngIf="dataHasLoaded">
<!-- the rest of your HTML -->
</ng-container>
This way you html will only start rendering once you have your data.
Upvotes: 0