5

I have a collapse-able panel which takes sometime to open as it has to render around 10K to 80K records, and for which I have used *ngFor. And since it takes a lot of time to render it appears as the application is crashed/stuck. So I wanted to show a loader, which we have in our product.

I am trying to emit the values from the child component to parent component where I want to show the loader(i.e block the parent component while the child component completes the rendering).

Below is my HTML code

  <li class="panel" *ngFor="let filter of filterData; let ind = index" id="qa-{{filter.NameFilterlet filter of filterData; let ind = index" id="qa-{{filter.NameFilter}}" >
    <div class="filter-list__cont-menu-item-name" [ngClass]="{'active': filter.NameFilter === selectedTitleFilter || resultFilter}"
       data-toggle="collapse" role="tab" [attr.data-target]="'#filter' + ind" aria-expanded="false"
      (click)="onTitleFilter(filter.NameFilter)">
      <fa-icon class="caretr" [icon]="['fas', 'caret-right']"></fa-icon>
      <span class="main-name">{{getNameFilter(filter)}}</span>
      
      
    
    </div>
    <div class="collapse filter-list__cont-sub-menu" [ngClass]="{'in': stateOpen}" role="tabpanel" id="filter{{ind}}"
      aria-expanded="false">
      <ul>
        <li *ngFor="let subFilter of filter.SubFilters" id="qa-{{subFilter.Name}}" (click)="onFilter(subFilter.Name, subFilter.Id, filter.NameFilter)"><div class="subFilter-name" data-toggle="tooltip" data-placement="right" title="{{subFilter.Name}}">{{subFilter.Name}}</div></li>
      </ul>
    </div>
  </li>

Below is my component.ts file code for on click of the tile which is expanded so show the records. I had tried setting the value to TRUE at the start and FALSE at the end, but since it is a method the TRUE value is turned to FALSE within a second.

  onTitleFilter(titleFilter: string) {
     this.startLoading.emit(true)
    if (!this.resultFilter) {
      this.selectedTitleFilter = this.selectedTitleFilter === titleFilter ? '' : titleFilter;
    }
    this.startLoading.emit(false)
  }

What can I do to show the loader while the *ngFor completes its rendering? Any solution?

oni3619
  • 153
  • 1
  • 9
  • 1
    If you are rendering 10K to 80K records in one request then obviously it will take some time to be render in browser. I suggest you to use pagination here for better performance.. – Nilesh Sonkusare Apr 02 '21 at 13:09
  • 1
    If not pagination you could use something like this: https://material.angular.io/cdk/scrolling/overview – Fussel Apr 02 '21 at 13:11
  • @NileshSonkusare pagination is not a choice over here. We do have the data on the page load, which doesnt take a lot of time to bring for the API, but for rendering it does take some time. – oni3619 Apr 02 '21 at 13:18
  • You can use the @ViewChildren for this.. Check this link: https://stackoverflow.com/a/49025047/6295845 – Nilesh Sonkusare Apr 02 '21 at 13:42
  • You could still use pagination in the Display, especially when you have the full data on Page load. See e. G. Material Paginator. Would seem a much better choice to me, who likes to scroll thru 80k entries...? – Loop Apr 02 '21 at 22:29

1 Answers1

1

Angular hook ngAfterViewInit migh seem a good place to handle this. However, you will face this nagging ExpressionChangedAfterItHasBeenCheckedError in your console. A reliable way of achieving what you need is to utilize the last variable on *ngFor.

This already answered SO query shows how to do it.

iwontcode
  • 74
  • 3