ng2-smart-таблица с подкачкой страниц из серверной части (Spring)

Я использую внутренний сервер (Java Spring) с включенным пейджером. Я загружаю 100 записей на страницу по HTTP-вызову.

В сервисе angular2 он использует вызов API с "? Page = 1 & size = 100" в качестве начального вызова, тогда как на клиентском пейджере размера он показывает 10 и перемещается до 10 страниц, что нормально. Но я не могу загрузить следующий кусок данных с сервера. Я проверил ServerDataSource и использовал.setPaging (1100).

Как я могу загрузить следующий кусок данных (2-200) и как мне этого добиться. Любые подсказки будут полезны.

@Injectable()
export class AmazonService extends ServerDataSource {

constructor(protected http: Http) {
    super(http);
}

public getAmazonInformation(page, size): Observable<Amazon[]> {

    let url = 'http://localhost:8080/plg-amazon?page=1&size=100';
    this.setPaging(1, 100, true);
    if (this.pagingConf && this.pagingConf['page'] && 
       this.pagingConf['perPage']) {
          url += 
       `page=${this.pagingConf['page']}&size=${this.pagingConf['perPage']}`;
}

return this.http.get(url).map(this.extractData).catch(this.handleError);
}

Спасибо!

6 ответов

Я решил эту проблему с LocalDataSource.

HTML

<ng2-smart-table [settings]="settings" [source]="source"></ng2-smart-table>

Т.С.

source: LocalDataSource = new LocalDataSource();
pageSize = 25;

ngOnInit() {
  this.source.onChanged().subscribe((change) => {
    if (change.action === 'page') {
      this.pageChange(change.paging.page);
    }
  });
}

pageChange(pageIndex) {
  const loadedRecordCount = this.source.count();
  const lastRequestedRecordIndex = pageIndex * this.pageSize;

  if (loadedRecordCount <= lastRequestedRecordIndex) {    
    let myFilter; //This is your filter.
    myFilter.startIndex = loadedRecordCount + 1;
    myFilter.recordCount = this.pageSize + 100; //extra 100 records improves UX.

    this.myService.getData(myFilter) //.toPromise()
      .then(data => {
        if (this.source.count() > 0)
          data.forEach(d => this.source.add(d));
        else
          this.source.load(data);
      })
  }
}

Попробуйте установить настройки для смарт-таблицы, как это

<ng2-smart-table #grid [settings]="settings" ... >

А на вашем компоненте определите настройки, примерно так:

  public settings: TableSettings = new TableSettings();

  ngOnInit(): void {
      ...
    this.settings.pager.display = true;
    this.settings.pager.perPage = 100;
    ...
  }

Также, если вам нужно настроить запрос на бэкэнд, есть параметры конфигурации для ServerDataSource это используется для извлечения данных / разбиения на страницы / сортировки.

Когда у вас есть конечная точка для некоторого объекта в {endPointBase}/ng2-smart-table, где вы обрабатываете параметры запроса key_like (например: @Requestparam Map to spring data Example), вы можете использовать на стороне клиента:

export class SpringDataSource extends ServerDataSource {
    constructor(http: HttpClient, endPointBase: string) {
        const serverSourceConf = new ServerSourceConf();
        serverSourceConf.dataKey = 'content';
        serverSourceConf.endPoint = endPointBase + `/ng2-smart-table`;
        serverSourceConf.pagerLimitKey = 'size';
        serverSourceConf.pagerPageKey = 'page';
        serverSourceConf.sortFieldKey = 'sort';
        serverSourceConf.totalKey = 'totalElements';

        super(http, serverSourceConf);
    }

    protected addPagerRequestParams(httpParams: HttpParams): HttpParams {
        const paging = this.getPaging();
        return httpParams
            .set(this.conf.pagerPageKey, (paging.page - 1).toString())
            .set(this.conf.pagerLimitKey, paging.perPage.toString());
    }

    protected addSortRequestParams(httpParams: HttpParams): HttpParams {
        const sort: {field: string, direction: string}[] = this.getSort();

        sort.forEach((column) => {
            httpParams = httpParams.append(this.conf.sortFieldKey, `${column.field},${column.direction}`);
        });
        return httpParams;
    }
}

Это мой способ решения всей этой проблемы.

1. Убедитесь, что в Backend (API) включена функция cors, чтобы клиент мог отображать заголовок «X-Pagination» следующим образом:

      app.UseCors(builder => builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin().WithExposedHeaders(new string[] { "X-Pagination"}));

2: HTML:

      <ng2-smart-table [settings]="settings" [source]="source"></ng2-smart-table>

3: ОБСЛУЖИВАНИЕ:

      getClients(pageNumber: number, pageSize: number): Observable<any> {
            const headers = new HttpHeaders({'Content-Type': 'application/json','Accept': 'application/json' });
            let params = new HttpParams();
            params = params.append('PageNumber',pageNumber.toString());
            params = params.append('PageSize',pageSize.toString());
            return this.http.get<ClientDto[]>(API_URL, {headers: headers, observe: "response" as "body",  responseType: "json", params} );
          }

4: TS:

      export class ListClientComponent implements OnInit {

  source: LocalDataSource;
  pageSize = 30;
  currentPage = 1;
  showPerPage = 10;
  totalCount;
  constructor(private service: ClientService,private router: Router) {
    this.initData();
  }

  public settings = {
    mode: 'external', 
    pager:{
      display: true,
      perPage: this.showPerPage,
    },
    actions: {
      add:false,
      edit:true,
      delete:false
    },
        columns: {
      clientId: {
        title: 'CI',
      },
      name: {
        title: 'Name'
      },
      instagramName: {
        title: 'Instagram'
      },
      type: {
        title: 'Type'
      },
      phone: {
        title: 'Phone'
      },
      gender: {
        title: 'Gender'
      },
      age: {
        title: 'Age'
      },
      city: {
        title: 'City'
      },
      email: {
        title: 'Email'
      }
    },
  };

  ngOnInit() {
    this.initOnChagedData();
  }

  onEdit(event){
    console.log(event.data.clientId);
    this.router.navigate(['/clients/update-client/'+ event.data.clientId]) ;  
  }

  initData(){
    this.source = new LocalDataSource();
    this.service.getClients(this.currentPage, this.pageSize).subscribe( (result: HttpResponse<any>) => {
      if(!result){
        return;
      }
      this.source.load(result.body);
      this.totalCount = JSON.parse(result.headers.get("X-Pagination"));
      this.totalCount = this.totalCount["totalCount"];
      console.log(this.source.count());
    }
    )
  }

  initOnChagedData(){
    this.source.onChanged().subscribe((change) => {
      if (change.action === 'page') {
        this.pageChange(change.paging.page);
      }
    });
  }

  pageChange(pageIndex) {
    var getNew = pageIndex * this.showPerPage;
    if( getNew >= this.source.count() && getNew < this.totalCount){
      this.currentPage = this.currentPage + 1;
      this.service.getClients(this.currentPage, this.pageSize).subscribe( result => {
        if(!result){
          return;
        }
        result.body.forEach(element => {
          this.source.add(element);
        });
      })
    }
  }
}

Вы должны заметить, что pageSize = общие данные, которые мы извлекаем из серверной части, а showPerPage = общие данные, которые мы показываем в таблице.

Алгоритм предназначен для извлечения из api только при необходимости, то есть когда клиент достигает страницы, где данные заканчиваются в памяти, он запрашивает еще 30 данных, чтобы иметь еще 3 страницы, а также не забывает другие 3 которые уже добывали раньше.

У меня была та же проблема, на которую указал @sovan, при работе с ng2-smart-table. После поиска быстрого исправления я попал в эту тему, которая была действительно полезной, особенно ответ @mohammed. Однако позже я узнал из этой темы, что лучший способ добиться этого — использовать «ServerDataSource» @Oleksandr Efymov. Ниже приведен полный пример кода для решения проблемы. проект с полным исходным кодом доступен на stackblitz здесь https://stackblitz.com/edit/angular-ivy-jlq4bf?file=src/app/app.component.ts.

//HTML-страница

      

//Класс компонента

      import { LocalDataSource, ServerDataSource } from 'ng2-smart-table';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent {
  name = 'Angular ' + VERSION.major;
  constructor(private _http: HttpClient) {
 this.initData();
}

  source: LocalDataSource;
  pageSize = 30;
  currentPage = 1;
  showPerPage = 30;
  totalCount;

  public settings = {
    mode: 'external',
    pager: {
      display: true,
      perPage: this.showPerPage,
    },
    actions: {
      add: false,
      edit: true,
      delete: false,
    },
    columns: {
      name: {
        title: 'Passenger Name',
      },
      trips: {
        title: 'Trips',
      },
      airline_name: {
        title: 'Airline Name',
        valuePrepareFunction: (idx, air) => {
          return `${air.airline[0].name}`;
        },
      },
      airline_country: {
        title: 'Airline Country',
        valuePrepareFunction: (idx, air) => {
          return `${air.airline[0].country}`;
        },
      },
    },
  };

  initData() {
    this.source = new ServerDataSource(this._http, {
      dataKey: 'data',
      endPoint: 'https://api.instantwebtools.net/v1/passenger',
      pagerPageKey: 'page', // this should be page number param name in endpoint (request not response) for example 'page'
      pagerLimitKey: 'size', // this should page size param name in endpoint (request not response)
      totalKey: 'totalPassengers', // this is total records count in response, this will handle pager
    });
  }
}

Примечание. «pagerPageKey» и «pagerLimitKey» — это фактическое имя параметра в вашей конечной точке. «totalKey» — это общая запись всех записей.

например: https://api.instantwebtools.net/v1/passenger?page=1&amp;amp;size=30

pagerPageKey:"страница" pagerLimitKey:"размер"

Важно отметить, что индексация страницы по умолчанию начинается с 1, и по умолчанию нет конфигурации для установки startindex. если ваша нумерация страниц начинается с 0, как в случае с конечной точкой API, используемой в приведенном выше примере, то есть быстрое исправление, предложенное по этой ссылке https://github.com/akveo/ng2-smart-table/issues/858# комментарий-439617491 . Все, что вам нужно сделать, это создать новый класс CustomServerDataSource, расширяющий класс ServerDataSource.

      import { HttpParams } from "@angular/common/http";
import { ServerDataSource } from "ng2-smart-table";

export class CustomServerDataSource extends ServerDataSource {
    addPagerRequestParams(httpParams: HttpParams): HttpParams {
        if (this.pagingConf && this.pagingConf['page'] && this.pagingConf['perPage']) {
            httpParams = httpParams.set(this.conf.pagerPageKey, this.pagingConf['page'] + (-1));
            httpParams = httpParams.set(this.conf.pagerLimitKey, this.pagingConf['perPage']);
        }
        return httpParams;
    }
}

Это также реализовано в исходном коде. просто раскомментируйте строку в методе intData, чтобы увидеть, как он работает.

Другие вопросы по тегам