Select 每页的项目到 Angular 并将参数发送到 Spring

Select items per page into Angular and send param to Spring

我正在尝试使用 Angular 实现 Spring 分页。我试过这段代码:

搜索 DTO:

public class ClassCategoriesSearchParams {
    private String title;
    private String type;
    private LocalDateTime publishedAt;
}

端点:

    @PostMapping("/find")
    public Page<ClassCategoriesFullDTO> search(@Valid ClassCategoriesSearchParams params, Pageable pageable) {

        Page<ClassCategoriesFullDTO> list = classCategoriesRestService.findClasses(params, pageable);
        return list;
    }

    public Page<ClassCategoriesFullDTO> findClasses(ClassCategoriesSearchParams params, Pageable pageable) {
        Specification<Product> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (params.getTitle() != null) {
                predicates.add(cb.equal(root.get("title"), params.getTitle()));
            }
            if (params.getType() != null) {
                predicates.add(cb.equal(root.get("type"), params.getType()));
            }
            if (params.getPublishedAt() != null) {
                predicates.add(cb.greaterThan(root.get("publishedAt"), params.getPublishedAt()));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        return classCategoriesService.findAll(spec, pageable).map(classCategoriesMapper::toFullDTO);
    }

Angular代码:

<div class="d-flex justify-content-between p-2">
        <ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="size" (pageChange)="pageChange($event)">
        </ngb-pagination>

        <select class="custom-select" style="width: auto" [(ngModel)]="size" (ngModelChange)="sizeChange($event)">
          <option [ngValue]="1">1 items per page</option>
          <option [ngValue]="2">2 items per page</option>
          <option [ngValue]="4">4 items per page</option>
          <option [ngValue]="6">6 items per page</option>
        </select>
      </div>

打字稿代码:

export class ClassListComponent implements OnInit {

  public page = 0;
  public size = 1;
  public totalItems = 0;

  public productList = [];

  public classes = [
    {
      id: null,
      productImage: null,
      summary: '',
      title: '',
      imgSrc: null
    }
  ];

  public loading = false;

  constructor(
    private _classService: ClassService,
    private sanitizer: DomSanitizer
  ) { }

  ngOnInit(): void {
    this.getClassList();
    this.getAllProducts();
  }

  private getClassList(): void {
    this._classService.getCategories().subscribe(
      data => {
        this.classes = [];
        this.classes = Object.values(data);
        this.classes.forEach(element => {
          this.getCategoryImage(element);
        });
      },
    );
  }

  public getCategoryImage(element): void {
    this.loading = true;
    this._classService.getCategoryImage(element.id).subscribe(
      data => {
        element.imgSrc = this.sanitizer.bypassSecurityTrustUrl(URL.createObjectURL(data));
        this.loading = false;
      }
    );
  }

  private getAllProducts(): void {
    this._classService.getAllProducts(this.page, this.size).subscribe(
      response => {
        this.productList = [];
        this.productList = response.content;
        this.totalItems = response.totalElements;
      }
    );
  }

  public pageChange(event): void {
    this.page = event - 1;
    this.getAllProducts();
  }

  public sizeChange(event): void {
    this.size = event;
    this.getAllProducts();
  }
}

服务:

 public getAllProducts(
    page?: number,
    size?: number
  ): Observable<GenericListDTO<any>> {
    let params = new HttpParams();
    if (page !== null) {
      params = params.set('page', page.toString());
    }
    if (size) {
      params = params.set('size', size.toString());
    }
    return this.http.post<GenericListDTO<any>>(`${this.url}/find`, {}, { params });
  }


export class GenericListDTO<T> {

  content: T[] = [];
  pageable: any = {};
  totalPages: number;
  totalElements: number;
  size: number;
  numberOfElements: number;
}

我有这个问题:当我将每页的项目数设置为 1 时,为了获得第一个项目,我需要发送参数 page = 0。我可以设置页面更改功能的逻辑来执行像预期的那样,但我的分页组件不会正确聚焦所选页面。也许这可以通过一些 css 覆盖来解决,但我认为更清晰的解决方案是在 BE 函数中更改它。您知道如何解决这个问题吗?

您可以为您的服务创建一个新的状态变量,减去一个而不是修改 page 变量。

另外,Spring 支持从 1 开始的索引分页。您可以通过两种方式配置

  1. spring.data.web.pageable.one-indexed-parameters=true 在您的应用程序属性中
  2. 通过java配置,修改resolver bean
PageableHandlerMethodArgumentResolver resolver = new PageableHandlerMethodArgumentResolver();
resolver.setOneIndexedParameters(true);

注意:这不是答案,只是评论

如果您使用的是 httpClient,post 必须是

this.http.post<GenericListDTO<any>>(`${this.url}/find`, {
   page:page,
   size:size,
});

忘记 httpParams 语法是 http.post(<url>,<obj>,<options>},见 the docs,第三个参数是选项,当你不发送 json 或者你需要一个特殊的 headers