Reputation: 3844
I want to load data from an angular service in a component constructor, and use these data to update the UI in the ngOnInit() function.
I am using the async-await feature to implement it.
Unfortunately, it does not work.
Here is my component source code:
import { Component, OnInit } from '@angular/core';
import {MonthlyCalendar} from './monthly-calendar';
import { MonthlyCalendarService } from './monthly-calendar.service';
import { resolve } from 'url';
@Component({
selector: 'app-table',
templateUrl: './table.component.html',
styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {
monthlyCalendar: MonthlyCalendar;
constructor(private monthlyCalendarService: MonthlyCalendarService) {
this.monthlyCalendar = null;
console.log('t0:' + new Date());
this._getData();
console.log('t2:' + new Date());
}
ngOnInit() {
console.log('t3:' + new Date());
console.log(this.monthlyCalendar);
}
async _getData() {
await this.monthlyCalendarService.getMonthlyCalendar(null, null)
.then((data: MonthlyCalendar) => {
console.log('t1:' + new Date());
this.monthlyCalendar = data;
})
.catch ((err: Error) => {
alert(err.stack);
});
}
}
Here is my service source code:
import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { MonthlyCalendar } from './monthly-calendar';
import { resolve, reject } from 'q';
@Injectable({
providedIn: 'root'
})
export class MonthlyCalendarService {
constructor(private http: HttpClient) { }
getMonthlyCalendar(year: number, month: number): Promise<object> {
const params = new HttpParams();
if (year != null) {
params.set('year', year.toString());
}
if (month != null) {
params.set('month', month.toString());
}
return this.http.get('backend/getMonthlyCalendar.php', {params}).toPromise();
}
}
Here is my component.html
<table>
<theader></theader>
<tbody></tbody>
</table>
I attached the screen dump for your reference.
Upvotes: 0
Views: 2577
Reputation: 10429
you can use Resolvers to load data before component load it will not load the route until data request is resolved below are some example for resolvers
https://codeburst.io/understanding-resolvers-in-angular-736e9db71267
https://alligator.io/angular/route-resolvers/
so first create a resolver like
import { Injectable } from '@angular/core';
import { Resolve } from '@angular/router';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';
@Injectable()
export class CalendarResolver implements Resolve<Observable<string>> {
constructor(private monthlyCalendarService: MonthlyCalendarService) {}
resolve() {
return this.monthlyCalendarService.getMonthlyCalendar(null, null);
}
}
Then add this resolver to your route
import { CalendarResolver } from './claendar.resolver';
{
path: 'yourpath',
component: yourcomponent,
resolve: { calander: CalendarResolver }
}
Add your resolvers to providers array of your module
then in your component
constructor(private activatedRoute: ActivatedRoute)
ngOnInit(){
this.monthlyCalander= this.route.snapshot.data['calander'];
}
Upvotes: 2
Reputation: 56
Angular has a very nice module HTTPClientModule. This is built on the top of RxJS Observable package.
The methods like 'get' of the HTTPClientModule, return observable, which we can subscribe in the components, and notify view to update the DOM.
Please read the official documentation
Upvotes: 0
Reputation: 1711
you have to change the code like this in constructor
this._getData().then(() =>
console.log('t2:' + new Date()
))
Upvotes: 0
Reputation: 24068
You can use a resolver for this
@Injectable()
export class MyResolver implements Resolve<SomeClass[]> {
constructor(private myService: MyService) {
}
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SomeClass[]> {
return this.myService.getAll().pipe(first());
}
}
In your router, you can register the resolver.
{
path: 'somepath',
component: MyComponent,
resolve: {
objects: MyResolver ,
}
},
Then you can access the resolved data like below in your component.
ngOnInit(): void {
this.route.data.subscribe((data: any) => {
this.objects = data['objects'];
});
}
Upvotes: 0