0

I am start doing some stuff in angular.

I implemented this example in my current project (the one named "Complete Example"):

https://ng-bootstrap.github.io/#/components/table/examples

Everything is working fine, However I have a simple question but I didn't find the answer nowhere. How can I put this example working with a real service? What stuff do I need to do?

I have already a Web api running and I tried some solutions but without success.

I did this in country.service.ts:

get countries$(): Observable<Country[]> {  
    return this.http.get<Country[]>(`${environment.apiUrl}/pois`);  
  }  

//get countries$() { return this._countries$.asObservable(); } 

  get total$(): Observable<any> {  
    return this.http.get(`${environment.apiUrl}/pois/total`);  
  }

  //get total$() { return this._total$.asObservable(); }

The data appear in my table but the example stopped working properly.

Is this the right way to put this example consuming a real service?

Thank you in advance.

Titus Sutio Fanpula
  • 3,467
  • 4
  • 14
  • 33
user1910232
  • 151
  • 1
  • 3
  • 12
  • I answered this question here: https://stackoverflow.com/a/67895973/3980374 but to sum it up, you'll need to call your API, populate a variable in the service and then use that for search/sort/filter. This will be client-side, server-side is a different animal entirely. – Jason Conville Jun 09 '21 at 00:27

1 Answers1

1

I love the work of ng-bootstrap's guys, but I think that, definetively is not a good example. In my opinion, to have all in a service is not clear.

I make something in this SO with material angular. In general you need an API with two functions

getLength(string filter)
//and 
getData(page:number,pageSize:number,filter:string,sortField:string,sortDirection:string)

In this anohter stackbliz is made it using ng-bootstrap

The idea is similar, we defined some auxiliar variables

  total: number;
  filter = new FormControl();
  page:number=1;
  pageSize:number=5;
  elements$:Observable<any>

  pag:BehaviorSubject<any>=new BehaviorSubject<any>(null);
  paginator$=this.pag.asObservable();

  sort:any={active:"position",direction:'desc'};
  isLoadingResults = true;

Anf in ngOnInit we subscribe to filter.valueChanges

const obsFilter=this.filter.valueChanges.pipe(
  debounceTime(200),
  startWith(null),
  switchMap((res: string) => this.dataService.getLength(res)),
  tap((res: number) => {
    this.page=1;
    this.total = res;
  })
);

this.elements$=merge(obsFilter, this.paginator$)
  .pipe(
    distinctUntilChanged(),
    switchMap(res => {
      return this.dataService.getData(
        this.page,
        this.pageSize,
        this.filter.value,
        this.sort.active,
        this.sort.direction
      );
    }),
    tap(_ => (this.isLoadingResults = false))
  )

We are going to use the auxiliar this.paginagtor$ that emit a value when the page or the pageSize change and when sort change, so our function sort becomes like

  onSort({column, direction}: SortEvent) {
    // resetting other headers
    this.sort={active:column,direction:direction}
    this.headers.forEach(header => {
      if (header.sortable !== column) {
        header.direction = '';
      }
    });
    this.pag.next(this.sort)
  }

And the .html (see how we split the [(ngModel)] in paginator)

<form>
  <div class="form-group form-inline">
      Full text search: <input class="form-control ml-2" type="text" name="searchTerm" [formControl]="filter"/>
      <span class="ml-3" *ngIf="isLoadingResults">Loading...</span>
  </div>

  <table class="table table-striped">
    <thead>
    <tr>
      <th scope="col" sortable="position" (sort)="onSort($event)">No.</th>
      <th scope="col" sortable="name" (sort)="onSort($event)">Name</th>
      <th scope="col" sortable="weight" (sort)="onSort($event)">Weight</th>
      <th scope="col" sortable="symbol" (sort)="onSort($event)">Symbol</th>
    </tr>
    </thead>
    <tbody>
    <tr *ngFor="let element of elements$ | async">
      <th scope="row">{{ element.position }}</th>
      <td>
        <ngb-highlight [result]="element.name" [term]="filter.value"></ngb-highlight>
      </td>
      <td><ngb-highlight [result]="element.weight | number" [term]="filter.value"></ngb-highlight></td>
      <td><ngb-highlight [result]="element.symbol" [term]="filter.value"></ngb-highlight></td>
    </tr>
    </tbody>
  </table>

  <div class="d-flex justify-content-between p-2">
    <ngb-pagination
      [collectionSize]="total" [page]="page" (pageChange)="page=$event;pag.next($event)" [pageSize]="pageSize">
    </ngb-pagination>

    <select class="custom-select" style="width: auto" name="pageSize" [ngModel]="pageSize" (ngModelChange)="pageSize=$event;pag.next(-pageSize)">
      <option [ngValue]="5">5 items per page</option>
      <option [ngValue]="10">10 items per page</option>
      <option [ngValue]="20">20 items per page</option>
    </select>
  </div>

</form>
Eliseo
  • 50,109
  • 4
  • 29
  • 67