The KNVB
The KNVB

Reputation: 3844

how to wait service load data complete?

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

Answers (4)

jitender
jitender

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

pranavkumar389
pranavkumar389

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

Ragulan
Ragulan

Reputation: 1711

you have to change the code like this in constructor

this._getData().then(() =>  
      console.log('t2:' + new Date()
      ))

Upvotes: 0

Lahiru Chandima
Lahiru Chandima

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

Related Questions