Reputation: 194
I've got a component which performs some calls to a service which calls an api. The component renders before these calls are finished, resulting in an empty page.
This is the code from the component:
import {Component, OnInit, OnDestroy} from '@angular/core';
import {AuthService} from '../services/auth.service';
import {AssignmentService} from '../services/assignment.service';
import {Assignment} from '../models/Assignment';
import {Request} from '../models/Request';
import {MeService} from '../services/me.service';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import {Router} from '@angular/router';
import {NavbarService} from '../services/navbar.service';
@Component({
selector: 'app-newrequest',
templateUrl: './newrequest.component.html',
providers: [AssignmentService]
})
export class NewrequestComponent implements OnInit {
me: MicrosoftGraph.User;
assignments: Assignment[];
requests: Request[] = [];
ready = false;
constructor(private meService: MeService,
private authService: AuthService,
private assignmentService: AssignmentService,
private router: Router,
public nav: NavbarService) {
}
ngOnInit() {
this.nav.show();
this.nav.element = 'newrequests';
if (localStorage.getItem('loggedin') === 'yes') {
this.meService.getMe().subscribe(data => {
this.me = data;
},
error => {
console.log(error);
},
() => this.assignmentService.getAssignments().subscribe(data => {
this.assignments = data;
},
error => {
console.log(error);
},
() => {
this.setRequests();
}));
} else {
this.router.navigate(['']);
}
}
onLogout() {
this.authService.logout();
}
onLogin() {
this.authService.login();
}
private setRequests() {
this.assignments.forEach(item => {
if (this.me.mail.toLowerCase() === item.lecturer.toLowerCase()) {
this.parseRequests(item.request, item.name);
}
});
this.ready = true;
}
private parseRequests(toSplit, name) {
const split = toSplit.split(',');
split.forEach(item => {
this.requests.push(new Request(item, name));
});
}
}
This is the code from the page:
<app-navbar-component></app-navbar-component>
<div *ngIf="ready">
<div *ngFor="let request of requests">
<p class="lead">{{request.user}}</p>
</div>
</div>
This is the function in my service:
getAssignments() {
return this.http.get(this.BASE_API_URL + '/assignments').catch(this.onError);
}
I get no errors. The requests are loaded (checked via console.log). The only problem is that the page renders before the data has finished loading.
Any ideas?
Thanks in advance!
Upvotes: 1
Views: 2259
Reputation: 3451
Have you tried using resolve?
create a resolver name it assignments-details.resolver.ts
import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot} from '@angular/router';
import {MeService} from '../services/me.service';
@Injectable()
export class AssignmentsDetailsResolver implements Resolve<any> {
constructor(api: MeService){}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
return this.api.getAssignments();
}
}
Then on your route config do it like this
{
path: 'your_path',
component: NewrequestComponent,
resolve: { AssignmentsDetails: AssignmentsDetailsResolver }
}
Then on your NewrequestComponent make sure you import ActivatedRoute
import { ActivatedRoute } from '@angular/router'
and in your contructor call it like this
constructor(private meService: MeService,
private authService: AuthService,
private assignmentService: AssignmentService,
private router: Router,
public nav: NavbarService,
private activateRoute: ActivatedRoute) {
this.activateRoute.data.subscribe((response) => {
//to get the response
console.log(response.AssignmentsDetails);
});
}
And also make sure you register 'AssignmentsDetailsResolver' in the provider property of your module.
Hope this helps you.
Upvotes: 2
Reputation: 222682
Yes Since the service call is asynchronous, the data does not arrive immediately when the subscribe is called.
But in your code, you are not setting ready variable to be true once the data is arrived. So you don't see any data on page. Set it to true once you get the data
this.me = data;
this.ready =true;
or handle through the safe navigation operator.
Upvotes: 0