首页 > 解决方案 > 将每页的项目选择到 Angular 中并将参数发送到 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);
    }

角代码:

<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 函数中更改它。你知道如何解决这个问题吗?

标签: angularspringspring-bootangular10angular11

解决方案


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

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

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

推荐阅读