问题描述
问题:由于我们的搜索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¤tPage=${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请求都将通过此拦截器。
-
与@tobi-or-not-tobi noted一样,最简单的方法是在
SearchConfig
中传递自定义动态参数。 -
当前,默认情况下,
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,} ); }
-
要实现目标(动态参数是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
。因此,您还需要自定义一个。