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;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, чтобы увидеть, как он работает.