排序不适用于自定义的 ProductListComponentService。(CustomProductListComponentService)

Sorting does not work for the customized ProductListComponentService.(CustomProductListComponentService)

Spartacus 在其产品列表页面的默认分页中列出了 10 种产品。但我希望它是 12。 在我的 .ts 文件中通常用于 PLP

protected productListComponentServiceDefault: ProductListComponentService,

我正在使用该结构。 但我通过自定义“ProductListComponentService”文件创建了“CutomProductListComponentService”。

受保护的 defaultPageSize = 12;

我通过添加完成了我想要的。分页共 12 件作品。

但是在这次定制之后,页面中的“排序”操作不再起作用了。

我在 CutomProductListComponentService 中添加了以下内容:

import { Injectable } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import {
  ActivatedRouterStateSnapshot,
  CurrencyService,
  LanguageService,
  ProductSearchPage,
  ProductSearchService,
  RouterState,
  RoutingService,
} from '@spartacus/core';
import { combineLatest, Observable, using } from 'rxjs';
import {
  debounceTime,
  distinctUntilChanged,
  filter,
  map,
  shareReplay,
  tap,
} from 'rxjs/operators';
// @ts-ignore
import { ProductListRouteParams, SearchCriteria } from './product-list.model';

/**
 * The `ProductListComponentService` is used to search products. The service is used
 * on the Product Listing Page, for listing products and the facet navigation.
 *
 * The service exposes the product search results based on the category and search
 * route parameters. The route parameters are used to query products by the help of
 * the `ProductSearchService`.
 */
@Injectable({ providedIn: 'root' })
export class CustomProductListComponentService {
  // TODO: make it configurable
  protected defaultPageSize = 12;

  protected readonly RELEVANCE_ALLCATEGORIES = ':relevance:allCategories:';

  constructor(
    protected productSearchService: ProductSearchService,
    protected routing: RoutingService,
    protected activatedRoute: ActivatedRoute,
    protected currencyService: CurrencyService,
    protected languageService: LanguageService,
    protected router: Router
  ) {}

  /**
   * Emits the search results for the current search query.
   *
   * The `searchResults$` is _not_ concerned with querying, it only observes the
   * `productSearchService.getResults()`
   */
  protected searchResults$: Observable<
    ProductSearchPage
    > = this.productSearchService
    .getResults()
    .pipe(filter((searchResult) => Object.keys(searchResult).length > 0));

  /**
   * Observes the route and performs a search on each route change.
   *
   * Context changes, such as language and currencies are also taken
   * into account, so that the search is performed again.
   */
  protected searchByRouting$: Observable<
    ActivatedRouterStateSnapshot
    > = combineLatest([
    this.routing.getRouterState().pipe(
      distinctUntilChanged((x, y) => {
        // router emits new value also when the anticipated `nextState` changes
        // but we want to perform search only when current url changes
        return x.state.url === y.state.url;
      })
    ),
    ...this.siteContext,
  ]).pipe(
    debounceTime(0),
    map(([routerState, ..._context]) => (routerState as RouterState).state),
    tap((state: ActivatedRouterStateSnapshot) => {
      const criteria = this.getCriteriaFromRoute(
        state.params,
        state.queryParams
      );
      this.search(criteria);
    })
  );

  /**
   * This stream is used for the Product Listing and Product Facets.
   *
   * It not only emits search results, but also performs a search on every change
   * of the route (i.e. route params or query params).
   *
   * When a user leaves the PLP route, the PLP component unsubscribes from this stream
   * so no longer the search is performed on route change.
   */
  readonly model$: Observable<ProductSearchPage> = using(
    () => this.searchByRouting$.subscribe(),
    () => this.searchResults$
  ).pipe(shareReplay({ bufferSize: 1, refCount: true }));

  /**
   * Expose the `SearchCriteria`. The search criteria are driven by the route parameters.
   *
   * This search route configuration is not yet configurable
   * (see https://github.com/SAP/spartacus/issues/7191).
   */
  protected getCriteriaFromRoute(
    routeParams: ProductListRouteParams,
    queryParams: SearchCriteria
  ): SearchCriteria {
    return {
      query: queryParams.query || this.getQueryFromRouteParams(routeParams),
      pageSize: queryParams.pageSize || this.defaultPageSize,
      currentPage: queryParams.currentPage,
      sortCode: queryParams.sortCode,
    };
  }

  /**
   * Resolves the search query from the given `ProductListRouteParams`.
   */
  protected getQueryFromRouteParams({
                                      query,
                                      categoryCode,
                                      brandCode,
                                    }: ProductListRouteParams) {
    if (query) {
      return query;
    }
    if (categoryCode) {
      return this.RELEVANCE_ALLCATEGORIES + categoryCode;
    }

    // TODO: drop support for brands as they should be treated
    // similarly as any category.
    if (brandCode) {
      return this.RELEVANCE_ALLCATEGORIES + brandCode;
    }
  }

  /**
   * Performs a search based on the given search criteria.
   *
   * The search is delegated to the `ProductSearchService`.
   */
  protected search(criteria: SearchCriteria): void {
    const currentPage = criteria.currentPage;
    const pageSize = criteria.pageSize;
    const sort = criteria.sortCode;

    this.productSearchService.search(
      criteria.query,
      // TODO: consider dropping this complex passing of cleaned object
      Object.assign(
        {},
        currentPage && { currentPage },
        pageSize && { pageSize },
        sort && { sort }
      )
    );
  }

  /**
   * Get items from a given page without using navigation
   */
  getPageItems(pageNumber: number): void {
    this.routing
      .getRouterState()
      .subscribe((route) => {
        const routeCriteria = this.getCriteriaFromRoute(
          route.state.params,
          route.state.queryParams
        );
        const criteria = {
          ...routeCriteria,
          currentPage: pageNumber,
        };
        this.search(criteria);
      })
      .unsubscribe();
  }

  /**
   * Sort the search results by the given sort code.
   */
  sort(sortCode: string): void {
    this.route({ sortCode });
  }

  /**
   * Routes to the next product listing page, using the given `queryParams`. The
   * `queryParams` support sorting, pagination and querying.
   *
   * The `queryParams` are delegated to the Angular router `NavigationExtras`.
   */
  protected route(queryParams: SearchCriteria): void {
    this.router.navigate([], {
      queryParams,
      queryParamsHandling: 'merge',
      relativeTo: this.activatedRoute,
    });
  }

  /**
   * The site context is used to update the search query in case of a
   * changing context. The context will typically influence the search data.
   *
   * We keep this private for now, as we're likely refactoring this in the next
   * major version.
   */
  private get siteContext(): Observable<string>[] {
    // TODO: we should refactor this so that custom context will be taken
    // into account automatically. Ideally, we drop the specific context
    // from the constructor, and query a ContextService for all contexts.

    return [this.languageService.getActive(), this.currencyService.getActive()];
  }
}

我在plp.ts中调用排序函数如下。

constructor(
    protected productListComponentService: CustomProductListComponentService,
    
  ) {}

sortList(sortCode: string): void {
    this.productListComponentService.sort(sortCode);
  }

排序过程不起作用。你能帮助我吗?非常感谢您。

您还需要将“ProductFacetService”中的“ProductListComponentService”替换为“CustomProductListComponentService”。

更好的方法是: 在“ProductListModule”的提供者中,添加:

{
  provide: ProductListComponentService,
  useClass: CustomProductListComponentService,
},