SPARTACUS自定义SearchboxComponent服务

问题描述

问题:由于我们的搜索API端点需要3个其他参数,因此我正在研究自定义搜索框配置。应该使用动态参数调用端点。

https:// localhost:9002 / occ / v2 / {baseSiteId} / products / customsearch / param1 / param2 / param3?query = xyz&pageSize = 5&lang = en&curr = USD&currentPage = 1

到目前为止,我已经收到以下指示:

searchBox组件将实际搜索委托给SearchBoxComponentService。该服务使用SearchBoxService,它是中央商店和较低级别的连接器/适配器的外立面。搜索框配置将传递到立面/商店中,您可以使用它来扩展以后端结尾的搜索查询

您应该开始提供SearchBoxComponentService的自定义版本,并覆盖search()方法。如果其他搜索参数与端点配置查询参数匹配,那么我相信您很好,但是老实说我是从头开始的,所以我可能会错过一些东西。

基于上述内容,我提出了以下建议:

search(query: string,config: SearchBoxConfig): Observable<SearchResults> {
    if (!query || query === '') {
        this.clearResults();
        return;
    }

    if (
        config.minCharactersBeforeRequest &&
        query.length < config.minCharactersBeforeRequest
    ) {
        return;
    }

    if (config.displayProducts) {
        this.ProductSearch(query, {
        pageSize: config.maxProducts,}).subscribe(data => {
        return data;
        }, error => {
        });
    }

    if (config.displaySuggestions) {
        this.searchService.searchSuggestions(query,{
        pageSize: config.maxSuggestions,});
    }
}

    
// tslint:disable-next-line: typedef
ProductSearch(query: string, searchConfig?: SearchConfig): Observable<SearchResults> {
    const pageSize = searchConfig.pageSize ? searchConfig.pageSize : 5;
    const currentPage = searchConfig.currentPage ? searchConfig.currentPage : 1;
    const fetchUrl = `${this.occEndpointsService.getBaseEndpoint()}/products/markethubsearch/${this.soldTo}/${this.shipTo}/${this.businessCategory}?query=${query}&pageSize=${pageSize}&lang=en&curr=USD&currentPage=${currentPage}`;
    
        return this.http.get<SearchResults>(fetchUrl, {
        params: new HttpParams().set('fields', 'FULL')
        });
}

但是,我仍然无法订阅可观察到的SearchResults。你能帮我吗?

解决方法

感谢您的提问。我想我最初是在闲暇时回答您的,但是我忽略了一些事情。

首先,SearchBoxComponentService.search不仅采用搜索配置并将其传递给SearchboxService。它仅从配置中获取细节。因此,我建议改写SearchboxService,即:

@Injectable({
  providedIn: 'root',})
export class CustomSearchboxService extends SearchboxService {
  search(query: string,config?: SearchConfig): void {
    super.search(query,{ ...config,foo: 'bar' } as SearchConfig);
  }
}

使用此设置,您的配置将最终进入操作状态,因此可以在OccProductSearchAdapter上使用。适配器将使用searchConfig创建端点。

您现在可以通过为Spartacus提供配置,使用动态参数来配置搜索端点:

provideConfig({
  backend: {
    occ: {
      endpoints: {
        productSearch:
          'products/search?fields=products(code)&foo=${foo}'
      }
    }
  }
})

但是,不允许允许动态路径属性。我将与团队联系,看看我们是否可以允许这样做。您也许可以更改端点,以改为使用查询参数,这很好。

要使用路径参数,请评估以下方法:

  • 自定义OccProductSearchAdapter并实现getSearchEndpoint。您可以利用searchConfig参数并输入path参数。
  • 引入一个角度拦截器。这不是很干净,因为所有http请求都将通过此拦截器。
,
  1. @tobi-or-not-tobi noted一样,最简单的方法是在SearchConfig中传递自定义动态参数。

  2. 当前,默认情况下,OccProductSearchAdapter.search()方法将SearchConfig对象的每个属性放入端点的查询参数中。因此,即使保留默认的端点形状,您也可以将自定义参数附加为查询参数:products/search?fields=...&query=...&pageSize=...&soldTo=...shipTo=...&businessCategory=...

    这是因为OccProductSearchAdapter.getSearchEndpoint()在通用网址生成器OccEndpointsService内部进行调用,同时将SearchConfig作为第三个参数传递(仅用于构建查询参数):

    protected getSearchEndpoint(
      query: string,searchConfig: SearchConfig
    ): string {
      return this.occEndpoints.getUrl(
        'productSearch',// endpoint name
        {},// url params for placeholders ${...}
        {                 // query params to append:
          query,...searchConfig,}
      );
    }
    
  3. 要实现目标(动态参数是url参数的一部分),您需要同时满足以下条件:

    i)在端点配置中添加${}占位符

    provideConfig({
      backend: {
        occ: {
          endpoints: {
            productSearch:
              'products/search/${shipTo}/${soldTo}/${businessCategory}?fields=FULL`'
          }
        }
      }
    })
    

    ii)自定义方法 OccProductSearchAdapter.getSearchEndpoint(),从SearchConfig对象中解压缩自定义参数,并将它们作为第二个参数传递给通用url构建器。例如,在您的app.module中,提供:

     @Injectable()
     export class CustomOccProductSearchAdapter extends OccProductSearchAdapter {
       protected getSearchEndpoint(
         query: string,searchConfig: SearchConfig
       ): string {
         // unpack custom params:
         const {
           shipTo,soldTo,businessCategory,...restSearchConfig
         } = searchConfig as any;
    
         return this.occEndpoints.getUrl(
           'productSearch',// endpoint name
           {                     // url params for placeholders ${...}:
             shipTo,},{                    // query params to append:
             query,...restSearchConfig,}
         );
       }
     }
    
     // AppModule:
     @NgModule({
       /* ... */
       providers: [
         {
           provide: ProductSearchAdapter,useClass: CustomOccProductSearchAdapter,]
    

注意:在@Nagaprasad Vendra中提到的 comment没有调用search()的{​​{1}}方法。需要说明的是:此服务仅处理辅助搜索结果(搜索框中的建议)。 CustomSearchboxService使用不同的外观获取搜索结果-ProductListingComponent。因此,您还需要自定义一个。