-1

I am trying to show a loading animation in Angular 10 while I am retrieving data. I can show the loading animation if I use a specific time value but I cannot get it to show just while the data is being gathered. Please see a snippet of my code below. Instead of manually calling the loading animation I would like it to only run while the 'getAllDocuments' function is running. Sometimes my hard coded time value is too short and others too long. I would like it to be correct every time.


ngOnInit() {
    this.getAllDocuments();
    this.triggerLoadingAnimation(12);
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }

  public triggerLoadingAnimation(num){
    this.spinner.show();

    setTimeout(() => {
      this.spinner.hide();
    }, num*1500);
  }

  async getAllDocuments() {
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
      this.dataSource.data = res as Document[];
    })
  }

jak dev
  • 33
  • 1
  • 8

5 Answers5

0

You were close.
I've also added error handling, remove unnecessary async, and run the ajax call in constructor instead of ngOnInit to avoid unnecessary waiting time.

constructor(private repoService: RepoService) {
    this.getAllDocuments();
}

ngOnInit() {
  // stuff that really need @Input data to be filled
}

ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
}

getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe((res: Document[]) => {
      this.dataSource.data = res;
      this.spinner.hide();
    },
    error => {
      this.spinner.hide();
      console.error('error while retrieving documents', error);
      // handle error
    })
}
Random
  • 3,158
  • 1
  • 15
  • 25
  • error method is not enough for any error you need to use finalize method to hide spinner – mr. pc_coder Sep 04 '20 at 14:37
  • this worked with minor tweaking thank you very much! – jak dev Sep 04 '20 at 15:37
  • 1
    @pc_coder I don't think so. `finalize` triggers on observable completion. For HTTP calls, it will always trigger error or success. Can you explicit a case where the observable would complete without triggering success or error handlers ? – Random Sep 04 '20 at 15:57
  • @Random, you are correct but in this case you have do the code twice, in success as well as in error, finalize is meant for these purposes – Mandeep Singh Sep 04 '20 at 18:21
  • @MandeepSingh I think error does not trigger finalize callback. There is no way to do the same as a `try/catch/finally` with Observables. – Random Sep 05 '20 at 08:06
0

You are doing it wrong, you should call the spinner to show when API call is made and hide it away when data is retrieved.

Better way is to call it in constructor as ngOnInit is called when finished creating a component DOM, injected all required dependencies through constructor and processed input bindings

constructor() {
    this.getAllDocuments();
}


ngOnInit() {
    //this.getAllDocuments();
  }

  ngAfterViewInit(): void {
    this.dataSource.sort = this.sort;
    this.dataSource.paginator = this.paginator;
  }

  async getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe((res: Document[]) => {
      this.dataSource.data = res;
    }, (err) => {
        //handle the errors
         console.log(err);
    }, () => {
        this.spinner.hide();
    });
  }
Mandeep Singh
  • 1,287
  • 14
  • 34
0

Loading a spinner is a good user experience technique but how many spinners will you need to load to satisfy the user? Probably depending on the size of the application. Since you need to show a spinner when the data is being retrieved, having a global spinner would be a much better way to go. With a global spinner, whenever data is being retrieved, the spinner will show. Below is a good implementation of an interceptor to show a spinner Using Interceptor to show spinner

Owen Kelvin
  • 14,054
  • 10
  • 41
  • 74
-1

You may use below code:

getAllDocuments() {
 this.spinner.show(); // SHOW WHEN DATA IS LOADING
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
      this.dataSource.data = res as Document[];
     this.spinner.hide();  //  HIDE WHEN DATA IS LOADED
    })
  }
abhay tripathi
  • 3,547
  • 4
  • 20
  • 25
-1

You can show and hide spinner in the same function rather than creating new function for that.

async getAllDocuments() {
    this.spinner.show();
    this.repoService.getData('/api/Prometheus/Documents')
    .subscribe(res => {
          this.dataSource.data = res as Document[];
          this.spinner.hide();
    });
    
}
Suroor Ahmmad
  • 1,110
  • 4
  • 23
  • 33