【问题标题】:ng2-smart-table with paging from back-end (Spring)ng2-smart-table 与后端分页(Spring)
【发布时间】:2017-11-23 23:54:05
【问题描述】:

我正在使用启用了 Pager 的后端服务器 (Java Spring)。我在 HTTP 调用上每页加载 100 条记录。

在 angular2 服务上,它使用“?page=1&size=100”作为初始调用的 API 调用,而在客户端大小的寻呼机上,它显示 10 并移动到 10 页,这很好。但我无法从服务器加载下一块数据。我检查了 ServerDataSource 并使用了 .setPaging(1,100)。

如何加载下一个数据块 (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);
}

谢谢!

【问题讨论】:

    标签: angular web pagination angular2-services ng2-smart-table


    【解决方案1】:

    我用LocalDataSource解决了这个问题。

    HTML

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

    TS

    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));
              this.source.getAll()
              .then(d => this.source.load(d))
          }
            else
              this.source.load(data);
          })
      }
    }
    

    【讨论】:

    • 感谢您的示例。 localDataSource 不完整时如何准确加载分页值。 IE。假设我有 10 页的 25 个数据项(总共 250 条记录),我在页面加载时加载了前 50 个,并且想在分页中向用户显示 10 个页面,所以当用户单击另一个页面时,它会动态加载数据(如果不存在)。
    • 嘿我用你的解决方案,但我得到了这个property 'then' does not exist on type 'object '
    • 我认为你应该取消注释 //.toPromise 部分。错误与您的“getData”函数有关。
    【解决方案2】:

    尝试像这样将设置设置为智能表

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

    然后在您的组件中定义设置,如下所示:

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

    【讨论】:

    • 谢谢,但这是用于客户端页面设置,它将在页面中显示 100 条记录,这是我对第一个请求的响应,但我的数据库有超过 100 条记录我想加载100 块。我的问题是,当我们到达第 100 个元素时,如何以及在何处使用(页面和大小)更新 http 请求 url。
    • smart-table 会为你添加参数到请求中:) 看看 ServerDataSource 的实现,github.com/akveo/ng2-smart-table/blob/master/src/…,方法 addPagerRequestOptions()
    【解决方案3】:

    另外,如果您需要自定义对后端的请求,还有ServerDataSource 的配置参数,用于数据检索/分页/排序。

    【讨论】:

      【解决方案4】:

      当您在 {endPointBase}/ng2-smart-table 上拥有某个实体的端点时, 您在哪里处理 key_like 请求参数 (即:@Requestparam 映射到弹簧数据示例) ,您可以在客户端使用:

      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;
          }
      }
      

      【讨论】:

      • 这个例子没有缓存。但是缓存是个问题,当我们可以在大表上使用基于数据库查询的排序和过滤时。快速从服务器检索 10 个项目。从服务器检索到的小页面改进了我们的用户体验。
      【解决方案5】:

      这是我解决所有这些问题的方法。

      1:确保后端 (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 = 我们从后端提取的总数据 每页显示 = 我们在表格中显示的总数据。

      该算法被设计为仅在必要时从API中提取,即当客户端到达数据在内存中结束的页面时,它要求再多30个数据有另外3个页面,并且也不会忘记之前已经提取的其他3个。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-08-15
        • 1970-01-01
        • 2019-08-10
        • 2020-07-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多