@searchstax-inc/searchstudio-ux-angular 1.2.51 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -1
- package/README.md +1188 -686
- package/esm2022/lib/components/searchstax-input/searchstax-input.component.mjs +6 -40
- package/esm2022/lib/components/searchstax-results/searchstax-results.component.mjs +5 -3
- package/esm2022/lib/components/searchstax-search-answer/searchstax-search-answer.component.mjs +4 -3
- package/esm2022/lib/components/searchstax-search-external/searchstax-search-external.component.mjs +4 -3
- package/esm2022/lib/components/searchstax-search-facets/searchstax-search-facets.component.mjs +5 -3
- package/esm2022/lib/components/searchstax-search-location/searchstax-search-location.component.mjs +4 -4
- package/esm2022/lib/components/searchstax-search-overview/searchstax-search-overview.component.mjs +4 -3
- package/esm2022/lib/components/searchstax-search-pagination/searchstax-search-pagination.component.mjs +5 -3
- package/esm2022/lib/components/searchstax-search-related/searchstax-search-related.component.mjs +4 -3
- package/esm2022/lib/components/searchstax-search-sorting/searchstax-search-sorting.component.mjs +4 -4
- package/esm2022/lib/components/templates/SearchstaxLocationWidgetTemplateConfig.mjs +91 -0
- package/esm2022/lib/components/templates/searchstax-search-answer-template.mjs +119 -0
- package/esm2022/lib/components/templates/searchstax-search-external-template.mjs +107 -0
- package/esm2022/lib/components/templates/searchstax-search-facet-desktop-template.mjs +207 -0
- package/esm2022/lib/components/templates/searchstax-search-facet-mobile-template.mjs +343 -0
- package/esm2022/lib/components/templates/searchstax-search-input-template.mjs +126 -0
- package/esm2022/lib/components/templates/searchstax-search-location-template.mjs +152 -0
- package/esm2022/lib/components/templates/searchstax-search-no-results-template.mjs +85 -0
- package/esm2022/lib/components/templates/searchstax-search-overview-template.mjs +87 -0
- package/esm2022/lib/components/templates/searchstax-search-pagination-infinite-template.mjs +60 -0
- package/esm2022/lib/components/templates/searchstax-search-pagination-template.mjs +96 -0
- package/esm2022/lib/components/templates/searchstax-search-related-template.mjs +81 -0
- package/esm2022/lib/components/templates/searchstax-search-results-template.mjs +171 -0
- package/esm2022/lib/components/templates/searchstax-search-sorting-template.mjs +76 -0
- package/esm2022/lib/searchstudio-ux-angular.module.mjs +70 -5
- package/esm2022/public-api.mjs +14 -1
- package/fesm2022/searchstax-inc-searchstudio-ux-angular.mjs +1840 -64
- package/fesm2022/searchstax-inc-searchstudio-ux-angular.mjs.map +1 -1
- package/lib/components/searchstax-input/searchstax-input.component.d.ts +11 -1
- package/lib/components/templates/SearchstaxLocationWidgetTemplateConfig.d.ts +13 -0
- package/lib/components/templates/searchstax-search-answer-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-external-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-facet-desktop-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-facet-mobile-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-input-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-location-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-no-results-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-overview-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-pagination-infinite-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-pagination-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-related-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-results-template.d.ts +7 -0
- package/lib/components/templates/searchstax-search-sorting-template.d.ts +7 -0
- package/lib/searchstudio-ux-angular.module.d.ts +16 -3
- package/package.json +2 -2
- package/public-api.d.ts +13 -0
package/README.md
CHANGED
|
@@ -51,7 +51,6 @@ Add following code to your ts file and fill config
|
|
|
51
51
|
afterSearch(results: ISearchstaxParsedResult[]) {
|
|
52
52
|
const copy = [...results]
|
|
53
53
|
// copy.splice(0, 1);
|
|
54
|
-
console.log('copy', copy);
|
|
55
54
|
return copy
|
|
56
55
|
}
|
|
57
56
|
|
|
@@ -154,142 +153,103 @@ Following widgets are available:
|
|
|
154
153
|
[sorting Widget](#sorting-widget)
|
|
155
154
|
|
|
156
155
|
### Answer Widget ###
|
|
156
|
+
SearchStax Site Search solution offers Angular widgets to assist in building your custom search page.
|
|
157
|
+
|
|
158
|
+
The AppSearchstaxAnswer component for Angular provides an AI answer widget for your searches.
|
|
159
|
+
|
|
160
|
+
**Usage**
|
|
157
161
|
|
|
158
|
-
example of answer widget initialization with minimum options
|
|
159
162
|
```
|
|
160
163
|
<app-searchstax-answer [showShowMoreAfterWordCount]="100"></app-searchstax-answer>
|
|
161
164
|
```
|
|
162
165
|
|
|
166
|
+
**Props**
|
|
167
|
+
|
|
168
|
+
- showShowMoreAfterWordCount - number(default 100) determining after how many symbols UI will show “Read More” view.
|
|
169
|
+
- feedbackWidget – an optional object that configures thumbs-up and thumbs-down feedback functionality.
|
|
163
170
|
|
|
164
|
-
|
|
171
|
+
Example of feedbackWidget config:
|
|
165
172
|
```
|
|
166
|
-
feedbackConfig = {
|
|
173
|
+
const feedbackConfig = {
|
|
167
174
|
renderFeedbackWidget: true,
|
|
168
|
-
emailOverride:
|
|
175
|
+
emailOverride: searchstaxEmailOverride,
|
|
169
176
|
thumbsUpValue: 10,
|
|
170
|
-
thumbsDownValue: 0
|
|
171
|
-
lightweightTemplateOverride: `
|
|
172
|
-
<div class="searchstax-lightweight-widget-container">
|
|
173
|
-
<div class="searchstax-lightweight-widget-thumbs-up {{#thumbsUpActive}}active{{/thumbsUpActive}}">
|
|
174
|
-
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
175
|
-
<path d="M4.85079 7.59996L7.83141 1C8.4243 1 8.9929 1.23178 9.41213 1.64436C9.83136 2.05694 10.0669 2.61651 10.0669 3.19999V6.1333H14.2845C14.5005 6.13089 14.7145 6.17474 14.9116 6.26179C15.1087 6.34885 15.2842 6.47704 15.426 6.63747C15.5677 6.79791 15.6723 6.98676 15.7326 7.19094C15.7928 7.39513 15.8072 7.60975 15.7748 7.81996L14.7465 14.4199C14.6926 14.7696 14.5121 15.0884 14.2382 15.3175C13.9643 15.5466 13.6156 15.6706 13.2562 15.6666H4.85079M4.85079 7.59996V15.6666M4.85079 7.59996H2.61531C2.22006 7.59996 1.84099 7.75448 1.5615 8.02953C1.28201 8.30458 1.125 8.67763 1.125 9.06661V14.1999C1.125 14.5889 1.28201 14.9619 1.5615 15.237C1.84099 15.512 2.22006 15.6666 2.61531 15.6666H4.85079" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
176
|
-
</svg>
|
|
177
|
-
</div>
|
|
178
|
-
<div class="searchstax-lightweight-widget-separator"></div>
|
|
179
|
-
<div class="searchstax-lightweight-widget-thumbs-down {{#thumbsDownActive}}active{{/thumbsDownActive}}">
|
|
180
|
-
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
181
|
-
<path d="M12.1492 9.06801L9.16859 15.668C8.5757 15.668 8.0071 15.4362 7.58787 15.0236C7.16864 14.611 6.93311 14.0515 6.93311 13.468V10.5347H2.71552C2.4995 10.5371 2.28552 10.4932 2.08842 10.4062C1.89132 10.3191 1.71581 10.1909 1.57405 10.0305C1.43229 9.87006 1.32766 9.6812 1.26743 9.47702C1.2072 9.27284 1.19279 9.05822 1.22521 8.84801L2.25353 2.24806C2.30742 1.89833 2.48793 1.57955 2.76179 1.35046C3.03566 1.12136 3.38443 0.997398 3.74384 1.0014H12.1492M12.1492 9.06801V1.0014M12.1492 9.06801H14.3847C14.7799 9.06801 15.159 8.91349 15.4385 8.63844C15.718 8.36339 15.875 7.99034 15.875 7.60135V2.46805C15.875 2.07907 15.718 1.70602 15.4385 1.43097C15.159 1.15592 14.7799 1.0014 14.3847 1.0014H12.1492" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
|
182
|
-
</svg>
|
|
183
|
-
|
|
184
|
-
</div>
|
|
185
|
-
</div>
|
|
186
|
-
`
|
|
177
|
+
thumbsDownValue: 0
|
|
187
178
|
}
|
|
188
|
-
<app-searchstax-answer [showShowMoreAfterWordCount]="100" [templateOverride]="answerTemplate" [feedbackwidget]="feedbackConfig">
|
|
189
|
-
<ng-template
|
|
190
|
-
#answerTemplate
|
|
191
|
-
let-answerData="answerData"
|
|
192
|
-
let-showMore="showMore"
|
|
193
|
-
let-context="context"
|
|
194
|
-
>
|
|
195
|
-
<div class="searchstax-answer-wrap">
|
|
196
|
-
<div class="searchstax-answer-icon"></div>
|
|
197
|
-
<div>
|
|
198
|
-
<div
|
|
199
|
-
[class]="
|
|
200
|
-
'searchstax-answer-container ' + answerData.showMoreButtonVisible
|
|
201
|
-
? 'searchstax-answer-show-more'
|
|
202
|
-
: ''
|
|
203
|
-
"
|
|
204
|
-
>
|
|
205
|
-
<div class="searchstax-answer-title">Smart Answers</div>
|
|
206
|
-
<div class="searchstax-answer-error" *ngIf="answerData.shouldShowAnswerError" [innerHTML]="answerData.answerErrorMessage"></div>
|
|
207
|
-
<div
|
|
208
|
-
class="searchstax-answer-description"
|
|
209
|
-
[innerHTML]="answerData.fullAnswerFormatted"
|
|
210
|
-
></div>
|
|
211
|
-
<div
|
|
212
|
-
*ngIf="answerData.answerLoading"
|
|
213
|
-
class="searchstax-answer-loading"
|
|
214
|
-
></div>
|
|
215
|
-
</div>
|
|
216
|
-
<div
|
|
217
|
-
*ngIf="answerData.showMoreButtonVisible"
|
|
218
|
-
class="searchstax-answer-load-more-button-container"
|
|
219
|
-
>
|
|
220
|
-
<button
|
|
221
|
-
class="searchstax-answer-load-more-button"
|
|
222
|
-
(click)="showMore($event, context)"
|
|
223
|
-
>
|
|
224
|
-
Read More
|
|
225
|
-
</button>
|
|
226
|
-
</div>
|
|
227
|
-
</div>
|
|
228
|
-
<div class="searchstax-answer-footer">
|
|
229
|
-
<div id="feedbackWidgetContainer"></div>
|
|
230
|
-
<div class="searchstax-lightweight-widget-separator-inline"></div>
|
|
231
|
-
<p class="searchstax-disclaimer">Generative AI is Experimental</p>
|
|
232
|
-
</div>
|
|
233
|
-
</div>
|
|
234
|
-
</ng-template>
|
|
235
|
-
</app-searchstax-answer>
|
|
236
179
|
```
|
|
237
180
|
|
|
238
|
-
|
|
181
|
+
|
|
182
|
+
**searchAnswerTemplate**
|
|
183
|
+
|
|
184
|
+
The templates prop allows customizing the answer UI.
|
|
185
|
+
|
|
186
|
+
It receives the following props:
|
|
187
|
+
|
|
188
|
+
- answerData – Data object of type: ISearchstaxAnswerData
|
|
189
|
+
- showMore - Handler for exiting the show more view
|
|
190
|
+
|
|
191
|
+
**Example**
|
|
192
|
+
|
|
239
193
|
```
|
|
240
|
-
<app-searchstax-answer [showShowMoreAfterWordCount]="100" [templateOverride]="answerTemplate">
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
194
|
+
<app-searchstax-answer [showShowMoreAfterWordCount]="100" [templateOverride]="answerTemplate" [feedbackwidget]="feedbackConfig">
|
|
195
|
+
<ng-template
|
|
196
|
+
#answerTemplate
|
|
197
|
+
let-answerData="answerData"
|
|
198
|
+
let-showMore="showMore"
|
|
199
|
+
let-context="context"
|
|
200
|
+
>
|
|
201
|
+
<div class="searchstax-answer-wrap">
|
|
202
|
+
<div class="searchstax-answer-icon"></div>
|
|
203
|
+
<div>
|
|
204
|
+
<div
|
|
205
|
+
[class]="{
|
|
206
|
+
'searchstax-answer-container': true,
|
|
207
|
+
'searchstax-answer-show-more': answerData.showMoreButtonVisible
|
|
208
|
+
}"
|
|
246
209
|
>
|
|
247
|
-
|
|
248
|
-
<div
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
[innerHTML]="answerData.fullAnswerFormatted"
|
|
262
|
-
></div>
|
|
263
|
-
<div
|
|
264
|
-
*ngIf="answerData.answerLoading"
|
|
265
|
-
class="searchstax-answer-loading"
|
|
266
|
-
></div>
|
|
267
|
-
</div>
|
|
268
|
-
<div
|
|
269
|
-
*ngIf="answerData.showMoreButtonVisible"
|
|
270
|
-
class="searchstax-answer-load-more-button-container"
|
|
271
|
-
>
|
|
272
|
-
<button
|
|
273
|
-
class="searchstax-answer-load-more-button"
|
|
274
|
-
(click)="showMore($event, context)"
|
|
275
|
-
>
|
|
276
|
-
Read More
|
|
277
|
-
</button>
|
|
278
|
-
</div>
|
|
279
|
-
</div>
|
|
280
|
-
<div class="searchstax-answer-footer">
|
|
281
|
-
<div id="feedbackWidgetContainer"></div>
|
|
282
|
-
<div class="searchstax-lightweight-widget-separator-inline"></div>
|
|
283
|
-
<p class="searchstax-disclaimer">Generative AI is Experimental</p>
|
|
284
|
-
</div>
|
|
210
|
+
<div class="searchstax-answer-title">Smart Answers</div>
|
|
211
|
+
<div
|
|
212
|
+
class="searchstax-answer-error"
|
|
213
|
+
*ngIf="answerData.shouldShowAnswerError"
|
|
214
|
+
[innerHTML]="answerData.answerErrorMessage"
|
|
215
|
+
></div>
|
|
216
|
+
<div
|
|
217
|
+
class="searchstax-answer-description"
|
|
218
|
+
[innerHTML]="answerData.fullAnswerFormatted"
|
|
219
|
+
></div>
|
|
220
|
+
<div
|
|
221
|
+
*ngIf="answerData.answerLoading"
|
|
222
|
+
class="searchstax-answer-loading"
|
|
223
|
+
></div>
|
|
285
224
|
</div>
|
|
286
|
-
|
|
225
|
+
<div
|
|
226
|
+
*ngIf="answerData.showMoreButtonVisible"
|
|
227
|
+
class="searchstax-answer-load-more-button-container"
|
|
228
|
+
>
|
|
229
|
+
<button
|
|
230
|
+
class="searchstax-answer-load-more-button"
|
|
231
|
+
(click)="showMore($event, context)"
|
|
232
|
+
>
|
|
233
|
+
Read More
|
|
234
|
+
</button>
|
|
235
|
+
</div>
|
|
236
|
+
</div>
|
|
237
|
+
<div class="searchstax-answer-footer">
|
|
238
|
+
<div id="feedbackWidgetContainer"></div>
|
|
239
|
+
<div class="searchstax-lightweight-widget-separator-inline"></div>
|
|
240
|
+
<p class="searchstax-disclaimer">Generative AI is Experimental</p>
|
|
241
|
+
</div>
|
|
242
|
+
</div>
|
|
243
|
+
</ng-template>
|
|
287
244
|
</app-searchstax-answer>
|
|
288
245
|
```
|
|
289
246
|
|
|
290
247
|
### Input Widget ###
|
|
291
248
|
|
|
292
|
-
|
|
249
|
+
The SearchStax Site Search solution offers an Angular input widget to assist with your custom search page.
|
|
250
|
+
|
|
251
|
+
The SearchstaxInputWidget component for Angular provides a search input with autosuggest/autocomplete functionality.
|
|
252
|
+
**Usage**
|
|
293
253
|
```
|
|
294
254
|
<app-searchstax-input
|
|
295
255
|
[afterAutosuggest]="afterAutosuggest"
|
|
@@ -298,8 +258,26 @@ example of input widget initialization with minimum options
|
|
|
298
258
|
></app-searchstax-input>
|
|
299
259
|
```
|
|
300
260
|
|
|
261
|
+
**Props**
|
|
262
|
+
|
|
263
|
+
- suggestAfterMinChars - default 3. Number of characters needed for autosuggest to start triggering
|
|
264
|
+
- beforeAutosuggest - callback function that gets called before firing autosuggest. autosuggestProps are being passed as a property and can be modified, if passed along further search will execute with modified properties, if null is returned then event gets canceled and search never fires.
|
|
265
|
+
- afterAutosuggest - callback function that gets called after autosuggest has values but before rendering. It needs to return same type of data but it can be modified.
|
|
266
|
+
- inputTemplate - template override. look at examples below
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
**inputWidgetTemplate**
|
|
270
|
+
|
|
271
|
+
The inputTemplate prop allows customizing the input UI.
|
|
301
272
|
|
|
302
|
-
|
|
273
|
+
It receives the following props:
|
|
274
|
+
|
|
275
|
+
- suggestions – Array of autosuggestion results
|
|
276
|
+
- onMouseLeave - Handler for mouse leave event
|
|
277
|
+
- onMouseOver - Handler for mouse over event
|
|
278
|
+
- onMouseClick - Handler for mouse click event
|
|
279
|
+
|
|
280
|
+
**example**
|
|
303
281
|
```
|
|
304
282
|
<app-searchstax-input
|
|
305
283
|
[afterAutosuggest]="afterAutosuggest"
|
|
@@ -307,344 +285,676 @@ example of input widget initialization with template override
|
|
|
307
285
|
[suggestAfterMinChars]="3"
|
|
308
286
|
[templateOverride]="inputTemplate"
|
|
309
287
|
>
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
288
|
+
<ng-template
|
|
289
|
+
#inputTemplate
|
|
290
|
+
let-suggestions="suggestions"
|
|
291
|
+
let-onMouseLeave="onMouseLeave"
|
|
292
|
+
let-onMouseOver="onMouseOver"
|
|
293
|
+
let-onMouseClick="onMouseClick"
|
|
294
|
+
let-context="context"
|
|
295
|
+
let-locationWidgetConfig="locationWidgetConfig"
|
|
296
|
+
>
|
|
297
|
+
<div class="searchstax-search-input-wrapper">
|
|
298
|
+
<input
|
|
299
|
+
type="text"
|
|
300
|
+
id="searchstax-search-input"
|
|
301
|
+
class="searchstax-search-input"
|
|
302
|
+
placeholder="SEARCH FOR..."
|
|
303
|
+
aria-label="search"
|
|
304
|
+
/>
|
|
305
|
+
<div
|
|
306
|
+
class="searchstax-autosuggest-container"
|
|
307
|
+
[ngClass]="{ hidden: suggestions.length === 0 }"
|
|
308
|
+
(mouseleave)="onMouseLeave(context)"
|
|
317
309
|
>
|
|
318
|
-
<div
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
class="searchstax-search-input"
|
|
323
|
-
placeholder="SEARCH FOR..."
|
|
324
|
-
/>
|
|
310
|
+
<div
|
|
311
|
+
class="searchstax-autosuggest-item"
|
|
312
|
+
*ngFor="let suggestion of suggestions"
|
|
313
|
+
>
|
|
325
314
|
<div
|
|
326
|
-
class="searchstax-autosuggest-container"
|
|
327
|
-
[
|
|
328
|
-
(
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
class="searchstax-autosuggest-item-term-container"
|
|
333
|
-
[innerHtml]="suggestion.term"
|
|
334
|
-
(mouseover)="onMouseOver(suggestion, context)"
|
|
335
|
-
(click)="onMouseClick($event, context)"
|
|
336
|
-
></div>
|
|
337
|
-
</div>
|
|
338
|
-
</div>
|
|
339
|
-
<button class="searchstax-spinner-icon" id="searchstax-search-input-action-button"></button>
|
|
315
|
+
class="searchstax-autosuggest-item-term-container"
|
|
316
|
+
[innerHtml]="suggestion.term"
|
|
317
|
+
(mouseover)="onMouseOver(suggestion, context)"
|
|
318
|
+
tabindex="0"
|
|
319
|
+
(click)="onMouseClick($event, context)"
|
|
320
|
+
></div>
|
|
340
321
|
</div>
|
|
341
|
-
</
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
<app-searchstax-search-location
|
|
325
|
+
[locationDecode]="locationWidgetConfig.locationDecode"
|
|
326
|
+
[locationDecodeCoordinatesToAddress]="
|
|
327
|
+
locationWidgetConfig.locationDecodeCoordinatesToAddress
|
|
328
|
+
"
|
|
329
|
+
[locationSearchEnabled]="locationWidgetConfig.locationSearchEnabled"
|
|
330
|
+
[locationValuesOverride]="locationWidgetConfig.locationValuesOverride"
|
|
331
|
+
>
|
|
332
|
+
</app-searchstax-search-location>
|
|
333
|
+
<button
|
|
334
|
+
class="searchstax-spinner-icon"
|
|
335
|
+
id="searchstax-search-input-action-button"
|
|
336
|
+
role="button"
|
|
337
|
+
aria-label="search"
|
|
338
|
+
></button>
|
|
339
|
+
</ng-template>
|
|
342
340
|
</app-searchstax-input>
|
|
343
341
|
```
|
|
344
342
|
### Location Widget ###
|
|
345
343
|
|
|
346
|
-
|
|
344
|
+
SearchStax Site Search solution offers a Angular search-location widget to assist with your custom search page.
|
|
345
|
+
|
|
346
|
+
The SearchstaxLocationWidget provides a location search input with location-based search functionality.
|
|
347
|
+
|
|
348
|
+
**Usage**
|
|
349
|
+
|
|
347
350
|
```
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
351
|
+
const config = {
|
|
352
|
+
appId: "APP_ID",
|
|
353
|
+
relatedSearchesAPIKey: "KEY"
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const locationWidgetConfig = {
|
|
357
|
+
locationDecode: (term: string): Promise<ISearchstaxLocation> => {
|
|
358
|
+
return new Promise((resolve) => {
|
|
359
|
+
// make a request to google geocoding API to retrieve lat, lon and address
|
|
360
|
+
|
|
361
|
+
const geocodingAPIKey = "GEOCODING_API_KEY";
|
|
362
|
+
const geocodingURL = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(
|
|
363
|
+
term
|
|
364
|
+
)}&key=${geocodingAPIKey}`;
|
|
365
|
+
fetch(geocodingURL)
|
|
366
|
+
.then((response) => response.json())
|
|
367
|
+
.then((data) => {
|
|
368
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
369
|
+
const result = data.results[0];
|
|
370
|
+
const location = {
|
|
371
|
+
lat: result.geometry.location.lat,
|
|
372
|
+
lon: result.geometry.location.lng,
|
|
373
|
+
address: result.formatted_address,
|
|
374
|
+
};
|
|
375
|
+
resolve(location);
|
|
376
|
+
} else {
|
|
377
|
+
resolve({
|
|
378
|
+
address: undefined,
|
|
379
|
+
lat: undefined,
|
|
380
|
+
lon: undefined,
|
|
381
|
+
error: true,
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
})
|
|
385
|
+
.catch(() => {
|
|
386
|
+
resolve({
|
|
387
|
+
address: undefined,
|
|
388
|
+
lat: undefined,
|
|
389
|
+
lon: undefined,
|
|
390
|
+
error: true,
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
});
|
|
394
|
+
},
|
|
395
|
+
locationDecodeCoordinatesToAddress: (lat: string, lon: string): Promise<ISearchstaxLocation> => {
|
|
360
396
|
return new Promise((resolve) => {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
397
|
+
fetch(
|
|
398
|
+
`https://geocoding-staging.searchstax.co/reverse?location=${lat},${lon}&components=country:US&app_id=${config.appId}`,
|
|
399
|
+
{
|
|
400
|
+
method: "GET",
|
|
401
|
+
headers: {
|
|
402
|
+
Authorization: `Token ${config.relatedSearchesAPIKey}`,
|
|
403
|
+
},
|
|
404
|
+
}
|
|
405
|
+
)
|
|
406
|
+
.then((response) => response.json())
|
|
407
|
+
.then((data) => {
|
|
408
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
409
|
+
const result = data.results[0];
|
|
410
|
+
resolve({
|
|
411
|
+
address: result.formatted_address,
|
|
412
|
+
lat: lat,
|
|
413
|
+
lon: lon,
|
|
414
|
+
error: false,
|
|
415
|
+
});
|
|
416
|
+
} else {
|
|
417
|
+
resolve({
|
|
418
|
+
address: undefined,
|
|
419
|
+
lat: lat,
|
|
420
|
+
lon: lon,
|
|
421
|
+
error: true,
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
})
|
|
425
|
+
.catch(() => {
|
|
426
|
+
resolve({
|
|
427
|
+
address: undefined,
|
|
428
|
+
lat: lat,
|
|
429
|
+
lon: lon,
|
|
430
|
+
error: true,
|
|
431
|
+
});
|
|
432
|
+
});
|
|
368
433
|
});
|
|
369
|
-
}
|
|
434
|
+
},
|
|
435
|
+
locationSearchEnabled: false,
|
|
436
|
+
locationValuesOverride: {
|
|
437
|
+
locationDistanceEnabled: true,
|
|
438
|
+
filterValues: ["any", "1000"],
|
|
439
|
+
filterUnit: "miles",
|
|
440
|
+
locationFilterDefaultValue: "any"
|
|
441
|
+
},
|
|
442
|
+
}
|
|
370
443
|
<app-searchstax-search-location
|
|
371
|
-
[locationDecode]="locationDecodeFunction"
|
|
372
|
-
[locationDecodeCoordinatesToAddress]="locationDecodeCoordinatesToAddress"
|
|
444
|
+
[locationDecode]="locationWidgetConfig.locationDecodeFunction"
|
|
445
|
+
[locationDecodeCoordinatesToAddress]="locationWidgetConfig.locationDecodeCoordinatesToAddress"
|
|
446
|
+
[locationValuesOverride]="locationWidgetConfig.locationValuesOverride"
|
|
447
|
+
[locationSearchEnabled]="locationWidgetConfig.locationSearchEnabled"
|
|
373
448
|
>
|
|
374
449
|
</app-searchstax-search-location>
|
|
375
450
|
```
|
|
376
|
-
|
|
451
|
+
|
|
452
|
+
**Props**
|
|
453
|
+
|
|
454
|
+
- locationDecode - callback function to override location decoding
|
|
455
|
+
- locationDecodeCoordinatesToAddress - callback function to override location decoding
|
|
456
|
+
|
|
457
|
+
**Template Override**
|
|
458
|
+
|
|
459
|
+
The searchLocationTemplate prop allows customizing the location input UI.
|
|
460
|
+
|
|
461
|
+
It receives the following props:
|
|
462
|
+
|
|
463
|
+
- locationData – data containing info on when to show certain elements
|
|
464
|
+
- inputValue – value of location input
|
|
465
|
+
- locationBlur - Handler for location input blur
|
|
466
|
+
- radiusChange - Handler for location radius change
|
|
467
|
+
- selectValue - Value of radius select
|
|
468
|
+
- inputChange - location input change handler
|
|
469
|
+
- locationError - boolean stating if location has error
|
|
470
|
+
- getCurrentLocation - Handler for getting current location from browser
|
|
471
|
+
|
|
472
|
+
|
|
473
|
+
**Example**
|
|
474
|
+
|
|
377
475
|
```
|
|
476
|
+
const config = {
|
|
477
|
+
appId: "APP_ID",
|
|
478
|
+
relatedSearchesAPIKey: "KEY"
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
const locationWidgetConfig = {
|
|
482
|
+
locationDecode: (term: string): Promise<ISearchstaxLocation> => {
|
|
483
|
+
return new Promise((resolve) => {
|
|
484
|
+
// make a request to google geocoding API to retrieve lat, lon and address
|
|
485
|
+
|
|
486
|
+
const geocodingAPIKey = "GEOCODING_API_KEY";
|
|
487
|
+
const geocodingURL = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(
|
|
488
|
+
term
|
|
489
|
+
)}&key=${geocodingAPIKey}`;
|
|
490
|
+
fetch(geocodingURL)
|
|
491
|
+
.then((response) => response.json())
|
|
492
|
+
.then((data) => {
|
|
493
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
494
|
+
const result = data.results[0];
|
|
495
|
+
const location = {
|
|
496
|
+
lat: result.geometry.location.lat,
|
|
497
|
+
lon: result.geometry.location.lng,
|
|
498
|
+
address: result.formatted_address,
|
|
499
|
+
};
|
|
500
|
+
resolve(location);
|
|
501
|
+
} else {
|
|
502
|
+
resolve({
|
|
503
|
+
address: undefined,
|
|
504
|
+
lat: undefined,
|
|
505
|
+
lon: undefined,
|
|
506
|
+
error: true,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
})
|
|
510
|
+
.catch(() => {
|
|
511
|
+
resolve({
|
|
512
|
+
address: undefined,
|
|
513
|
+
lat: undefined,
|
|
514
|
+
lon: undefined,
|
|
515
|
+
error: true,
|
|
516
|
+
});
|
|
517
|
+
});
|
|
518
|
+
});
|
|
519
|
+
},
|
|
520
|
+
locationDecodeCoordinatesToAddress: (lat: string, lon: string): Promise<ISearchstaxLocation> => {
|
|
521
|
+
return new Promise((resolve) => {
|
|
522
|
+
fetch(
|
|
523
|
+
`https://geocoding-staging.searchstax.co/reverse?location=${lat},${lon}&components=country:US&app_id=${config.appId}`,
|
|
524
|
+
{
|
|
525
|
+
method: "GET",
|
|
526
|
+
headers: {
|
|
527
|
+
Authorization: `Token ${config.relatedSearchesAPIKey}`,
|
|
528
|
+
},
|
|
529
|
+
}
|
|
530
|
+
)
|
|
531
|
+
.then((response) => response.json())
|
|
532
|
+
.then((data) => {
|
|
533
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
534
|
+
const result = data.results[0];
|
|
535
|
+
resolve({
|
|
536
|
+
address: result.formatted_address,
|
|
537
|
+
lat: lat,
|
|
538
|
+
lon: lon,
|
|
539
|
+
error: false,
|
|
540
|
+
});
|
|
541
|
+
} else {
|
|
542
|
+
resolve({
|
|
543
|
+
address: undefined,
|
|
544
|
+
lat: lat,
|
|
545
|
+
lon: lon,
|
|
546
|
+
error: true,
|
|
547
|
+
});
|
|
548
|
+
}
|
|
549
|
+
})
|
|
550
|
+
.catch(() => {
|
|
551
|
+
resolve({
|
|
552
|
+
address: undefined,
|
|
553
|
+
lat: lat,
|
|
554
|
+
lon: lon,
|
|
555
|
+
error: true,
|
|
556
|
+
});
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
},
|
|
560
|
+
locationSearchEnabled: false,
|
|
561
|
+
locationValuesOverride: {
|
|
562
|
+
locationDistanceEnabled: true,
|
|
563
|
+
filterValues: ["any", "1000"],
|
|
564
|
+
filterUnit: "miles",
|
|
565
|
+
locationFilterDefaultValue: "any"
|
|
566
|
+
},
|
|
567
|
+
}
|
|
378
568
|
<app-searchstax-search-location
|
|
379
|
-
[locationDecode]="locationDecode"
|
|
569
|
+
[locationDecode]="locationWidgetConfig.locationDecode"
|
|
380
570
|
[templateOverride]="locationTemplate"
|
|
381
|
-
[
|
|
571
|
+
[locationValuesOverride]="locationWidgetConfig.locationValuesOverride"
|
|
572
|
+
[locationSearchEnabled]="locationWidgetConfig.locationSearchEnabled"
|
|
573
|
+
[locationDecodeCoordinatesToAddress]="locationWidgetConfig.locationDecodeCoordinatesToAddress"
|
|
574
|
+
>
|
|
575
|
+
<ng-template
|
|
576
|
+
#locationTemplate
|
|
577
|
+
let-context="context"
|
|
578
|
+
let-locationData="locationData"
|
|
579
|
+
let-inputValue="inputValue"
|
|
580
|
+
let-selectValue="selectValue"
|
|
581
|
+
let-radiusChange="radiusChange"
|
|
582
|
+
let-inputChange="inputChange"
|
|
583
|
+
let-locationBlur="locationBlur"
|
|
584
|
+
let-locationError="locationError"
|
|
585
|
+
let-getCurrentLocation="getCurrentLocation"
|
|
586
|
+
>
|
|
587
|
+
<div
|
|
588
|
+
class="searchstax-location-input-container"
|
|
589
|
+
data-test-id="searchstax-location-input-container"
|
|
590
|
+
*ngIf="locationData"
|
|
591
|
+
>
|
|
592
|
+
<div class="searchstax-location-input-wrapper">
|
|
593
|
+
<span class="searchstax-location-input-label">NEAR</span>
|
|
594
|
+
<div class="searchstax-location-input-wrapper-inner">
|
|
595
|
+
<input
|
|
596
|
+
type="text"
|
|
597
|
+
id="searchstax-location-input"
|
|
598
|
+
class="searchstax-location-input"
|
|
599
|
+
[ngClass]="{
|
|
600
|
+
'searchstax-input-location-error': locationError
|
|
601
|
+
}"
|
|
602
|
+
placeholder="Zip, Postal Code or City..."
|
|
603
|
+
aria-label="Search Location Input"
|
|
604
|
+
data-test-id="searchstax-location-input"
|
|
605
|
+
[value]="inputValue"
|
|
606
|
+
(change)="inputChange($event, context)"
|
|
607
|
+
(blur)="locationBlur(context)"
|
|
608
|
+
/>
|
|
609
|
+
<button
|
|
610
|
+
(click)="getCurrentLocation(context)"
|
|
611
|
+
class="searchstax-get-current-location-button"
|
|
612
|
+
>
|
|
613
|
+
Use my current location
|
|
614
|
+
</button>
|
|
615
|
+
</div>
|
|
616
|
+
<span
|
|
617
|
+
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
618
|
+
class="searchstax-location-input-label"
|
|
619
|
+
>WITHIN</span
|
|
620
|
+
>
|
|
621
|
+
<select
|
|
622
|
+
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
623
|
+
id="searchstax-location-radius-select"
|
|
624
|
+
class="searchstax-location-radius-select"
|
|
625
|
+
aria-label="Search Location Radius Select"
|
|
626
|
+
data-test-id="searchstax-location-radius-select"
|
|
627
|
+
(change)="radiusChange($event, context)"
|
|
628
|
+
[(ngModel)]="context.selectValue"
|
|
382
629
|
>
|
|
383
|
-
<
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
let-locationData="locationData"
|
|
387
|
-
let-inputValue="inputValue"
|
|
388
|
-
let-selectValue="selectValue"
|
|
389
|
-
let-radiusChange="radiusChange"
|
|
390
|
-
let-inputChange="inputChange"
|
|
391
|
-
let-locationBlur="locationBlur"
|
|
392
|
-
let-locationError="locationError"
|
|
393
|
-
let-getCurrentLocation="getCurrentLocation"
|
|
630
|
+
<option
|
|
631
|
+
*ngFor="let value of locationData.locationSearchDistanceValues"
|
|
632
|
+
[value]="value.value"
|
|
394
633
|
>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
<div class="searchstax-location-input-wrapper-inner">
|
|
403
|
-
<input
|
|
404
|
-
type="text"
|
|
405
|
-
id="searchstax-location-input"
|
|
406
|
-
class="searchstax-location-input"
|
|
407
|
-
[ngClass]="{
|
|
408
|
-
'searchstax-input-location-error': locationError
|
|
409
|
-
}"
|
|
410
|
-
placeholder="Zip, Postal Code or City..."
|
|
411
|
-
aria-label="Search Location Input"
|
|
412
|
-
data-test-id="searchstax-location-input"
|
|
413
|
-
[value]="inputValue"
|
|
414
|
-
(change)="inputChange($event, context)"
|
|
415
|
-
(blur)="locationBlur(context)"
|
|
416
|
-
/>
|
|
417
|
-
<button
|
|
418
|
-
(click)="getCurrentLocation(context)"
|
|
419
|
-
class="searchstax-get-current-location-button"
|
|
420
|
-
>
|
|
421
|
-
Use my current location
|
|
422
|
-
</button>
|
|
423
|
-
</div>
|
|
424
|
-
<span
|
|
425
|
-
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
426
|
-
class="searchstax-location-input-label"
|
|
427
|
-
>WITHIN</span
|
|
428
|
-
>
|
|
429
|
-
<select
|
|
430
|
-
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
431
|
-
id="searchstax-location-radius-select"
|
|
432
|
-
class="searchstax-location-radius-select"
|
|
433
|
-
aria-label="Search Location Radius Select"
|
|
434
|
-
data-test-id="searchstax-location-radius-select"
|
|
435
|
-
(change)="radiusChange($event, context)"
|
|
436
|
-
[(ngModel)]="context.selectValue"
|
|
437
|
-
>
|
|
438
|
-
<option
|
|
439
|
-
*ngFor="
|
|
440
|
-
let value of locationData.locationSearchDistanceValues
|
|
441
|
-
"
|
|
442
|
-
[value]="value.value"
|
|
443
|
-
>
|
|
444
|
-
{{ value.label }}
|
|
445
|
-
</option>
|
|
446
|
-
</select>
|
|
447
|
-
</div>
|
|
448
|
-
</div>
|
|
449
|
-
</ng-template>
|
|
634
|
+
{{ value.label }}
|
|
635
|
+
</option>
|
|
636
|
+
</select>
|
|
637
|
+
</div>
|
|
638
|
+
</div>
|
|
639
|
+
</ng-template>
|
|
640
|
+
|
|
450
641
|
</app-searchstax-search-location>
|
|
451
642
|
```
|
|
643
|
+
|
|
452
644
|
### Result Widget ###
|
|
453
645
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
```
|
|
646
|
+
The SearchStax Site Search solution offers an Angular results widget to assist with your custom search page.
|
|
647
|
+
|
|
648
|
+
The SearchstaxResultsWidget for Angular component displays the search results.
|
|
649
|
+
|
|
650
|
+
**Usage**
|
|
460
651
|
|
|
461
|
-
example of results widget initialization with minimum options and infinite scroll behavior
|
|
462
652
|
```
|
|
463
653
|
<app-searchstax-results
|
|
464
654
|
[afterLinkClick]="afterLinkClick"
|
|
465
|
-
[renderMethod]="'infiniteScroll'"
|
|
466
655
|
></app-searchstax-results>
|
|
467
656
|
```
|
|
468
657
|
|
|
469
|
-
|
|
658
|
+
**Result Template Override**
|
|
659
|
+
|
|
660
|
+
The resultsTemplate prop allows customizing the result UI.
|
|
661
|
+
|
|
662
|
+
It receives following props:
|
|
663
|
+
- searchResults - Array of result items
|
|
664
|
+
- resultClicked - Handler for result click events
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
**No Results Template Override**
|
|
668
|
+
|
|
669
|
+
The noResultTemplate prop allows customizing the result UI.
|
|
670
|
+
|
|
671
|
+
It receives following props:
|
|
672
|
+
|
|
673
|
+
- searchResults - Array of result items
|
|
674
|
+
- resultClicked - Handler for result click events
|
|
675
|
+
- searchTerm - Search input term
|
|
676
|
+
- metadata - Metadata object
|
|
677
|
+
- executeSearch - Handler for executing srearch
|
|
678
|
+
- store - Main store of app
|
|
679
|
+
|
|
680
|
+
**Example of default render method**
|
|
470
681
|
```
|
|
471
682
|
<app-searchstax-results
|
|
472
683
|
[afterLinkClick]="afterLinkClick"
|
|
473
684
|
[resultsTemplate]="resultsTemplate"
|
|
474
685
|
[noResultsTemplate]="noResultsTemplate"
|
|
475
686
|
>
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
687
|
+
<ng-template
|
|
688
|
+
#resultsTemplate
|
|
689
|
+
let-searchResults="searchResults"
|
|
690
|
+
let-resultClicked="resultClicked"
|
|
691
|
+
let-isImage="isImage"
|
|
692
|
+
let-context="context"
|
|
693
|
+
>
|
|
694
|
+
<div class="searchstax-search-results">
|
|
695
|
+
<a
|
|
696
|
+
*ngFor="let searchResult of searchResults"
|
|
697
|
+
[href]="searchResult.url"
|
|
698
|
+
[attr.data-searchstax-unique-result-id]="searchResult.uniqueId"
|
|
699
|
+
(click)="resultClicked(searchResult, $event, context)"
|
|
700
|
+
(keyup.enter)="resultClicked(searchResult, $event, context)"
|
|
701
|
+
(keyup.space)="resultClicked(searchResult, $event, context)"
|
|
702
|
+
tabindex="0"
|
|
703
|
+
class="searchstax-result-item-link searchstax-result-item-link-wrapping"
|
|
704
|
+
>
|
|
705
|
+
<div
|
|
706
|
+
class="searchstax-search-result"
|
|
707
|
+
[ngClass]="{ 'has-thumbnail': searchResult.thumbnail }"
|
|
708
|
+
>
|
|
709
|
+
<div
|
|
710
|
+
*ngIf="searchResult.promoted"
|
|
711
|
+
class="searchstax-search-result-promoted"
|
|
712
|
+
></div>
|
|
713
|
+
<div
|
|
714
|
+
*ngIf="searchResult.ribbon"
|
|
715
|
+
[innerHTML]="searchResult.ribbon"
|
|
716
|
+
class="searchstax-search-result-ribbon"
|
|
717
|
+
></div>
|
|
718
|
+
<img
|
|
719
|
+
alt=""
|
|
720
|
+
*ngIf="searchResult.thumbnail"
|
|
721
|
+
[src]="searchResult.thumbnail"
|
|
722
|
+
class="searchstax-thumbnail"
|
|
723
|
+
/>
|
|
724
|
+
<div class="searchstax-search-result-title-container">
|
|
725
|
+
<span
|
|
726
|
+
class="searchstax-search-result-title"
|
|
727
|
+
[innerHTML]="searchResult.title"
|
|
728
|
+
></span>
|
|
729
|
+
</div>
|
|
730
|
+
<p
|
|
731
|
+
*ngIf="searchResult.paths"
|
|
732
|
+
class="searchstax-search-result-common"
|
|
733
|
+
[innerHTML]="searchResult.paths"
|
|
734
|
+
></p>
|
|
735
|
+
<p
|
|
736
|
+
*ngIf="searchResult.description"
|
|
737
|
+
[innerHTML]="searchResult.description"
|
|
738
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
739
|
+
></p>
|
|
740
|
+
<div *ngFor="let unmappedField of searchResult.unmappedFields">
|
|
741
|
+
<div
|
|
742
|
+
*ngIf="isImage(unmappedField)"
|
|
743
|
+
class="searchstax-search-result-image-container"
|
|
744
|
+
>
|
|
745
|
+
<img
|
|
746
|
+
alt=""
|
|
747
|
+
[src]="unmappedField.value"
|
|
748
|
+
class="searchstax-result-image"
|
|
749
|
+
/>
|
|
536
750
|
</div>
|
|
537
|
-
<div>
|
|
538
|
-
<p
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
<p>Lost? Click on the ‘X” in the Search Box to reset your search.</p>
|
|
751
|
+
<div *ngIf="!isImage(unmappedField)">
|
|
752
|
+
<p
|
|
753
|
+
class="searchstax-search-result-common"
|
|
754
|
+
[innerHTML]="unmappedField.value"
|
|
755
|
+
></p>
|
|
543
756
|
</div>
|
|
544
|
-
</
|
|
757
|
+
</div>
|
|
758
|
+
</div>
|
|
759
|
+
</a>
|
|
760
|
+
</div>
|
|
761
|
+
</ng-template>
|
|
762
|
+
<ng-template
|
|
763
|
+
#noResultsTemplate
|
|
764
|
+
let-metadata="metadata"
|
|
765
|
+
let-searchTerm="searchTerm"
|
|
766
|
+
let-executeSearch="executeSearch"
|
|
767
|
+
let-context="context"
|
|
768
|
+
>
|
|
769
|
+
<div class="searchstax-no-results">
|
|
770
|
+
Showing <strong>no results</strong> for
|
|
771
|
+
<strong>"{{ searchTerm }}"</strong>
|
|
772
|
+
<br />
|
|
773
|
+
<span *ngIf="metadata?.spellingSuggestion"
|
|
774
|
+
> Did you mean
|
|
775
|
+
<a
|
|
776
|
+
href="#"
|
|
777
|
+
[attr.aria-label]="'did you mean: ' + metadata?.spellingSuggestion"
|
|
778
|
+
class="searchstax-suggestion-term"
|
|
779
|
+
(click)="
|
|
780
|
+
executeSearch(metadata?.spellingSuggestion ?? '', $event, context)
|
|
781
|
+
"
|
|
782
|
+
>{{ metadata?.spellingSuggestion }}</a
|
|
783
|
+
>?</span
|
|
784
|
+
>
|
|
785
|
+
</div>
|
|
786
|
+
<ul>
|
|
787
|
+
<li>
|
|
788
|
+
Try searching for search related terms or topics. We offer a wide
|
|
789
|
+
variety of content to help you get the information you need.
|
|
790
|
+
</li>
|
|
791
|
+
<li>Lost? Click on the ‘X” in the Search Box to reset your search.</li>
|
|
792
|
+
</ul>
|
|
793
|
+
</ng-template>
|
|
794
|
+
|
|
545
795
|
</app-searchstax-results>
|
|
546
796
|
```
|
|
547
797
|
|
|
798
|
+
**Example of infinite scroll and pagination render methods**
|
|
799
|
+
```
|
|
800
|
+
<app-searchstax-results
|
|
801
|
+
[afterLinkClick]="afterLinkClick"
|
|
802
|
+
[renderMethod]="'infiniteScroll'"
|
|
803
|
+
></app-searchstax-results>
|
|
804
|
+
|
|
805
|
+
|
|
806
|
+
```
|
|
807
|
+
|
|
548
808
|
### Pagination Widget ###
|
|
549
809
|
|
|
810
|
+
The SearchStax Site Search solution offers an Angular pagination widget to assist with you custom search page.
|
|
811
|
+
|
|
812
|
+
The SearchstaxPaginationWidget for Angular displays pagination controls for search results.
|
|
813
|
+
|
|
814
|
+
**Usage**
|
|
550
815
|
|
|
551
|
-
example of pagination widget initialization with minimum options
|
|
552
816
|
```
|
|
553
817
|
<app-searchstax-search-pagination></app-searchstax-search-pagination>
|
|
554
818
|
```
|
|
555
819
|
|
|
556
|
-
|
|
820
|
+
**Main Template Override**
|
|
821
|
+
|
|
822
|
+
Main template for the pagination controls.
|
|
823
|
+
|
|
824
|
+
It receives following props:
|
|
825
|
+
|
|
826
|
+
- paginationData – Pagination info object
|
|
827
|
+
- previousPage – Handler for previous page click
|
|
828
|
+
- nextPage - – Handler for next page click
|
|
829
|
+
|
|
830
|
+
|
|
831
|
+
**Infinite Scroll Template Override**
|
|
832
|
+
|
|
833
|
+
Main template for the pagination controls in infinite scroll mode.
|
|
834
|
+
|
|
835
|
+
It receives following props:
|
|
836
|
+
- isLastPage - boolean, true if its last page
|
|
837
|
+
- results - results.length can be used if there are results
|
|
838
|
+
|
|
839
|
+
**Example**
|
|
840
|
+
|
|
557
841
|
```
|
|
558
842
|
<app-searchstax-search-pagination [templateOverride]="paginationTemplate">
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
843
|
+
<ng-template
|
|
844
|
+
#paginationTemplate
|
|
845
|
+
let-paginationData="paginationData"
|
|
846
|
+
let-previousPage="previousPage"
|
|
847
|
+
let-nextPage="nextPage"
|
|
848
|
+
let-context="context"
|
|
849
|
+
>
|
|
850
|
+
<div class="searchstax-pagination-container">
|
|
851
|
+
<div class="searchstax-pagination-content">
|
|
852
|
+
<a
|
|
853
|
+
class="searchstax-pagination-previous"
|
|
854
|
+
[class]="paginationData.isFirstPage ? 'disabled' : ''"
|
|
855
|
+
(click)="previousPage($event, context)"
|
|
856
|
+
(keyup.enter)="previousPage($event, context)"
|
|
857
|
+
(keyup.space)="previousPage($event, context)"
|
|
858
|
+
tabindex="0"
|
|
859
|
+
id="searchstax-pagination-previous"
|
|
860
|
+
>
|
|
861
|
+
< Previous
|
|
862
|
+
</a>
|
|
863
|
+
<div class="searchstax-pagination-details">
|
|
864
|
+
{{ paginationData?.startResultIndex }} -
|
|
865
|
+
{{ paginationData?.endResultIndex }} of
|
|
866
|
+
{{ paginationData?.totalResults }}
|
|
867
|
+
</div>
|
|
868
|
+
<a
|
|
869
|
+
class="searchstax-pagination-next"
|
|
870
|
+
[class]="paginationData.isLastPage ? 'disabled' : ''"
|
|
871
|
+
(click)="nextPage($event, context)"
|
|
872
|
+
(keyup.enter)="nextPage($event, context)"
|
|
873
|
+
(keyup.space)="nextPage($event, context)"
|
|
874
|
+
tabindex="0"
|
|
875
|
+
id="searchstax-pagination-next"
|
|
876
|
+
>Next ></a
|
|
877
|
+
>
|
|
878
|
+
</div>
|
|
879
|
+
</div>
|
|
880
|
+
</ng-template>
|
|
881
|
+
</app-searchstax-search-pagination>
|
|
882
|
+
|
|
883
|
+
// infinite scroll example
|
|
590
884
|
|
|
591
|
-
example of pagination widget with infinite scroll
|
|
592
|
-
```
|
|
593
885
|
<app-searchstax-search-pagination [templateOverride]="paginationTemplate"
|
|
594
886
|
[infiniteScrollTemplateOverride]="infiniteScrollTemplate">
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
887
|
+
<ng-template
|
|
888
|
+
#infiniteScrollTemplate
|
|
889
|
+
let-paginationData="paginationData"
|
|
890
|
+
let-nextPage="nextPage"
|
|
891
|
+
let-context="context"
|
|
892
|
+
>
|
|
893
|
+
<div class="searchstax-pagination-container">
|
|
894
|
+
<div class="searchstax-pagination-content">
|
|
895
|
+
<a
|
|
896
|
+
class="searchstax-pagination-load-more"
|
|
897
|
+
(click)="nextPage($event, context)"
|
|
898
|
+
(keyup.enter)="nextPage($event, context)"
|
|
899
|
+
(keyup.space)="nextPage($event, context)"
|
|
900
|
+
tabindex="0"
|
|
901
|
+
>
|
|
902
|
+
Load More
|
|
903
|
+
</a>
|
|
904
|
+
</div>
|
|
905
|
+
</div>
|
|
906
|
+
</ng-template>
|
|
907
|
+
<ng-template
|
|
908
|
+
#paginationTemplate
|
|
909
|
+
let-paginationData="paginationData"
|
|
910
|
+
let-previousPage="previousPage"
|
|
911
|
+
let-nextPage="nextPage"
|
|
912
|
+
let-context="context"
|
|
913
|
+
>
|
|
914
|
+
<div class="searchstax-pagination-container">
|
|
915
|
+
<div class="searchstax-pagination-content">
|
|
916
|
+
<a
|
|
917
|
+
class="searchstax-pagination-previous"
|
|
918
|
+
[class]="paginationData.isFirstPage ? 'disabled' : ''"
|
|
919
|
+
(click)="previousPage($event, context)"
|
|
920
|
+
(keyup.enter)="previousPage($event, context)"
|
|
921
|
+
(keyup.space)="previousPage($event, context)"
|
|
922
|
+
tabindex="0"
|
|
923
|
+
id="searchstax-pagination-previous"
|
|
924
|
+
>
|
|
925
|
+
< Previous
|
|
926
|
+
</a>
|
|
927
|
+
<div class="searchstax-pagination-details">
|
|
928
|
+
{{ paginationData?.startResultIndex }} -
|
|
929
|
+
{{ paginationData?.endResultIndex }} of
|
|
930
|
+
{{ paginationData?.totalResults }}
|
|
931
|
+
</div>
|
|
932
|
+
<a
|
|
933
|
+
class="searchstax-pagination-next"
|
|
934
|
+
[class]="paginationData.isLastPage ? 'disabled' : ''"
|
|
935
|
+
(click)="nextPage($event, context)"
|
|
936
|
+
(keyup.enter)="nextPage($event, context)"
|
|
937
|
+
(keyup.space)="nextPage($event, context)"
|
|
938
|
+
tabindex="0"
|
|
939
|
+
id="searchstax-pagination-next"
|
|
940
|
+
>Next ></a
|
|
941
|
+
>
|
|
942
|
+
</div>
|
|
943
|
+
</div>
|
|
944
|
+
</ng-template>
|
|
642
945
|
</app-searchstax-search-pagination>
|
|
643
946
|
```
|
|
644
947
|
|
|
645
948
|
### Facets Widget ###
|
|
646
949
|
|
|
647
|
-
|
|
950
|
+
The SearchStax Site Search solution offers the SearchstaxFacetsWidget for Angular to display the search facets.
|
|
951
|
+
|
|
952
|
+
**Facet Selection and Order**
|
|
953
|
+
|
|
954
|
+
Facet lists are configured and ordered on the Site Search [Faceting Tab](https://www.searchstax.com/docs/searchstudio/faceting-tab/).
|
|
955
|
+
|
|
956
|
+
**Usage**
|
|
957
|
+
|
|
648
958
|
```
|
|
649
959
|
<app-searchstax-search-facets
|
|
650
960
|
[facetingType]="'showUnavailable'"
|
|
@@ -653,8 +963,50 @@ example of facets widget initialization with minimum options
|
|
|
653
963
|
></app-searchstax-search-facets>
|
|
654
964
|
```
|
|
655
965
|
|
|
966
|
+
**Props**
|
|
967
|
+
|
|
968
|
+
- facetingType: "and" | "or" | "showUnavailable" | "tabs"; // type that determines how facets will behave
|
|
969
|
+
- specificFacets?: string[]; // optional array of facet names that if provided will only render those facets
|
|
970
|
+
- itemsPerPageDesktop: number; // default expanded facets for desktop
|
|
971
|
+
- itemsPerPageMobile: number; // default expanded facets for mobile
|
|
972
|
+
|
|
973
|
+
|
|
974
|
+
**Main Template Desktop Override**
|
|
975
|
+
|
|
976
|
+
Main wrapper template for desktop facets display.
|
|
977
|
+
|
|
978
|
+
It receives following props:
|
|
979
|
+
- facetsTemplateDataDesktop - Facets data object
|
|
980
|
+
- isNotDeactivated - Check if facet group is active
|
|
981
|
+
- toggleFacetGroup - Toggle facet group active state
|
|
982
|
+
- isChecked - Check if facet value is selected
|
|
983
|
+
- selectFacet - Handler for facet select
|
|
984
|
+
- showMoreLessDesktop - Show more/less facets handler
|
|
985
|
+
- facetContainers - Object of facet DOM containers
|
|
986
|
+
- updateRefDesktop - Handler for keeping checkbox references
|
|
656
987
|
|
|
657
|
-
|
|
988
|
+
|
|
989
|
+
**Main Template Mobile Override**
|
|
990
|
+
|
|
991
|
+
Main wrapper template for mobile facets display.
|
|
992
|
+
|
|
993
|
+
It receives following props:
|
|
994
|
+
- facetsTemplateDataMobile - Facets data object
|
|
995
|
+
- selectedFacetsCheckboxes - Selected facet values
|
|
996
|
+
- isNotDeactivated - Check if facet group is active
|
|
997
|
+
- toggleFacetGroup - Toggle facet group active state
|
|
998
|
+
- isChecked - Check if facet value is selected
|
|
999
|
+
- selectFacet - Handler for facet select
|
|
1000
|
+
- showMoreLessDesktop - Show more/less facets handler
|
|
1001
|
+
- facetContainers - Object of facet DOM containers
|
|
1002
|
+
- openOverlay - Handler to open mobile overlay
|
|
1003
|
+
- unselectFacet - Handler to unselect specific facet
|
|
1004
|
+
- unselectAll - Handler to unselect all facets
|
|
1005
|
+
- closeOverlay - Handler to close mobile overlay
|
|
1006
|
+
- updateRefMobile - Handler for keeping mobile checkbox references
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
**Example**
|
|
658
1010
|
```
|
|
659
1011
|
<app-searchstax-search-facets
|
|
660
1012
|
[facetingType]="'showUnavailable'"
|
|
@@ -663,371 +1015,521 @@ example of facets widget initialization with template overrides
|
|
|
663
1015
|
[templateOverrideDesktop]="templateOverrideDesktop"
|
|
664
1016
|
[templateOverrideMobile]="templateOverrideMobile"
|
|
665
1017
|
>
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
1018
|
+
<ng-template
|
|
1019
|
+
#templateOverrideDesktop
|
|
1020
|
+
let-facetsTemplateDataDesktop="facetsTemplateDataDesktop"
|
|
1021
|
+
let-isNotDeactivated="isNotDeactivated"
|
|
1022
|
+
let-context="context"
|
|
1023
|
+
let-toggleFacetGroup="toggleFacetGroup"
|
|
1024
|
+
let-facetValues="facetValues"
|
|
1025
|
+
let-isChecked="isChecked"
|
|
1026
|
+
let-selectFacet="selectFacet"
|
|
1027
|
+
let-showMoreLessDesktop="showMoreLessDesktop"
|
|
1028
|
+
>
|
|
1029
|
+
<div class="searchstax-facets-container-desktop">
|
|
1030
|
+
<div
|
|
1031
|
+
class="searchstax-facet-container"
|
|
1032
|
+
*ngFor="let facet of facetsTemplateDataDesktop?.facets"
|
|
1033
|
+
[class]="{ active: isNotDeactivated(facet.name, context) }"
|
|
1034
|
+
>
|
|
1035
|
+
<div>
|
|
1036
|
+
<div
|
|
1037
|
+
class="searchstax-facet-title-container"
|
|
1038
|
+
(click)="toggleFacetGroup(facet.name, context)"
|
|
676
1039
|
>
|
|
677
|
-
<div class="searchstax-
|
|
1040
|
+
<div class="searchstax-facet-title">
|
|
1041
|
+
{{ facet.label }}
|
|
1042
|
+
</div>
|
|
1043
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
1044
|
+
</div>
|
|
1045
|
+
<div class="searchstax-facet-values-container" aria-live="polite">
|
|
1046
|
+
<div
|
|
1047
|
+
*ngFor="let facetValue of facetValues(facet); index as key"
|
|
1048
|
+
class="searchstax-facet-value-container"
|
|
1049
|
+
[class]="{
|
|
1050
|
+
'searchstax-facet-value-disabled': facetValue.disabled
|
|
1051
|
+
}"
|
|
1052
|
+
#ref
|
|
1053
|
+
>
|
|
1054
|
+
<div class="searchstax-facet-input">
|
|
1055
|
+
<input
|
|
1056
|
+
type="checkbox"
|
|
1057
|
+
class="searchstax-facet-input-checkbox"
|
|
1058
|
+
[checked]="isChecked(facetValue, context)"
|
|
1059
|
+
[attr.aria-label]="
|
|
1060
|
+
facetValue.value + ' ' + facetValue.count
|
|
1061
|
+
"
|
|
1062
|
+
[disabled]="facetValue.disabled"
|
|
1063
|
+
(click)="
|
|
1064
|
+
selectFacet(ref, $event, facetValue, true, context)
|
|
1065
|
+
"
|
|
1066
|
+
/>
|
|
1067
|
+
</div>
|
|
678
1068
|
<div
|
|
679
|
-
class="searchstax-facet-
|
|
680
|
-
|
|
681
|
-
[class]="{ active: isNotDeactivated(facet.name, context) }"
|
|
1069
|
+
class="searchstax-facet-value-label"
|
|
1070
|
+
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
682
1071
|
>
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
({{ facetValue.count }})
|
|
715
|
-
</div>
|
|
716
|
-
</div>
|
|
717
|
-
<div class="searchstax-facet-show-more-container" *ngIf="facet.hasMoreFacets">
|
|
718
|
-
<div
|
|
719
|
-
class="searchstax-facet-show-more-container"
|
|
720
|
-
(click)="showMoreLessDesktop($event, facet, context)"
|
|
721
|
-
>
|
|
722
|
-
<div
|
|
723
|
-
*ngIf="facet.showingAllFacets"
|
|
724
|
-
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
725
|
-
>
|
|
726
|
-
less
|
|
727
|
-
</div>
|
|
728
|
-
<div
|
|
729
|
-
*ngIf="!facet.showingAllFacets"
|
|
730
|
-
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
731
|
-
>
|
|
732
|
-
more
|
|
733
|
-
</div>
|
|
734
|
-
</div>
|
|
735
|
-
</div>
|
|
736
|
-
</div>
|
|
1072
|
+
{{ facetValue.value }}
|
|
1073
|
+
</div>
|
|
1074
|
+
<div
|
|
1075
|
+
class="searchstax-facet-value-count"
|
|
1076
|
+
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
1077
|
+
>
|
|
1078
|
+
({{ facetValue.count }})
|
|
1079
|
+
</div>
|
|
1080
|
+
</div>
|
|
1081
|
+
<div
|
|
1082
|
+
class="searchstax-facet-show-more-container"
|
|
1083
|
+
*ngIf="facet.hasMoreFacets"
|
|
1084
|
+
>
|
|
1085
|
+
<div
|
|
1086
|
+
class="searchstax-facet-show-more-container"
|
|
1087
|
+
(click)="showMoreLessDesktop($event, facet, context)"
|
|
1088
|
+
(keyup.enter)="showMoreLessDesktop($event, facet, context)"
|
|
1089
|
+
(keyup.space)="showMoreLessDesktop($event, facet, context)"
|
|
1090
|
+
tabindex="0"
|
|
1091
|
+
>
|
|
1092
|
+
<div
|
|
1093
|
+
*ngIf="facet.showingAllFacets"
|
|
1094
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
1095
|
+
>
|
|
1096
|
+
less
|
|
1097
|
+
</div>
|
|
1098
|
+
<div
|
|
1099
|
+
*ngIf="!facet.showingAllFacets"
|
|
1100
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
1101
|
+
>
|
|
1102
|
+
more
|
|
737
1103
|
</div>
|
|
738
1104
|
</div>
|
|
739
1105
|
</div>
|
|
740
|
-
</
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1106
|
+
</div>
|
|
1107
|
+
</div>
|
|
1108
|
+
</div>
|
|
1109
|
+
</div>
|
|
1110
|
+
</ng-template>
|
|
1111
|
+
<ng-template
|
|
1112
|
+
#templateOverrideMobile
|
|
1113
|
+
let-isNotDeactivated="isNotDeactivated"
|
|
1114
|
+
let-context="context"
|
|
1115
|
+
let-toggleFacetGroup="toggleFacetGroup"
|
|
1116
|
+
let-facetValues="facetValues"
|
|
1117
|
+
let-isChecked="isChecked"
|
|
1118
|
+
let-selectFacet="selectFacet"
|
|
1119
|
+
let-openOverlay="openOverlay"
|
|
1120
|
+
let-selectedFacetsCheckboxes="selectedFacetsCheckboxes"
|
|
1121
|
+
let-unselectFacet="unselectFacet"
|
|
1122
|
+
let-unselectAll="unselectAll"
|
|
1123
|
+
let-facetMobileData="facetMobileData"
|
|
1124
|
+
let-facetsTemplateDataMobile="facetsTemplateDataMobile"
|
|
1125
|
+
let-closeOverlay="closeOverlay"
|
|
1126
|
+
let-showMoreLessDesktop="showMoreLessDesktop"
|
|
1127
|
+
let-showMoreLessMobile="showMoreLessMobile"
|
|
1128
|
+
>
|
|
1129
|
+
<div class="searchstax-facets-container-mobile">
|
|
1130
|
+
<div class="searchstax-facets-pills-container">
|
|
1131
|
+
<div
|
|
1132
|
+
class="searchstax-facets-pill searchstax-facets-pill-filter-by"
|
|
1133
|
+
(click)="openOverlay(context)"
|
|
1134
|
+
>
|
|
1135
|
+
<div class="searchstax-facets-pill-label">Filter By</div>
|
|
1136
|
+
</div>
|
|
1137
|
+
<div class="searchstax-facets-pills-selected">
|
|
1138
|
+
<div
|
|
1139
|
+
class="searchstax-facets-pill searchstax-facets-pill-facets"
|
|
1140
|
+
*ngFor="let facet of selectedFacetsCheckboxes"
|
|
1141
|
+
(click)="unselectFacet(facet, context)"
|
|
1142
|
+
>
|
|
1143
|
+
<div class="searchstax-facets-pill-label">
|
|
1144
|
+
{{ facet.value }} ({{ facet.count }})
|
|
1145
|
+
</div>
|
|
1146
|
+
<div class="searchstax-facets-pill-icon-close"></div>
|
|
1147
|
+
</div>
|
|
1148
|
+
</div>
|
|
1149
|
+
<div
|
|
1150
|
+
class="searchstax-facets-pill searchstax-clear-filters searchstax-facets-pill-clear-all"
|
|
1151
|
+
*ngIf="selectedFacetsCheckboxes.length"
|
|
1152
|
+
(click)="unselectAll(context)"
|
|
1153
|
+
>
|
|
1154
|
+
<div class="searchstax-facets-pill-label">Clear Filters</div>
|
|
1155
|
+
</div>
|
|
1156
|
+
</div>
|
|
1157
|
+
<div
|
|
1158
|
+
class="searchstax-facets-mobile-overlay"
|
|
1159
|
+
[class]="{
|
|
1160
|
+
'searchstax-show': facetMobileData(facetsTemplateDataMobile)
|
|
1161
|
+
?.overlayOpened
|
|
1162
|
+
}"
|
|
1163
|
+
>
|
|
1164
|
+
<div class="searchstax-facets-mobile-overlay-header">
|
|
1165
|
+
<div class="searchstax-facets-mobile-overlay-header-title">
|
|
1166
|
+
Filter By
|
|
1167
|
+
</div>
|
|
1168
|
+
<div
|
|
1169
|
+
class="searchstax-search-close"
|
|
1170
|
+
(click)="closeOverlay(context)"
|
|
1171
|
+
></div>
|
|
1172
|
+
</div>
|
|
1173
|
+
<div class="searchstax-facets-container-mobile">
|
|
1174
|
+
<div
|
|
1175
|
+
*ngFor="let facet of facetsTemplateDataMobile?.facets"
|
|
1176
|
+
class="searchstax-facet-container"
|
|
1177
|
+
[class]="{
|
|
1178
|
+
active: isNotDeactivated(facet.name, context)
|
|
1179
|
+
}"
|
|
757
1180
|
>
|
|
758
|
-
<div
|
|
759
|
-
<div
|
|
760
|
-
|
|
761
|
-
|
|
1181
|
+
<div>
|
|
1182
|
+
<div
|
|
1183
|
+
class="searchstax-facet-title-container"
|
|
1184
|
+
(click)="toggleFacetGroup(facet.name, context)"
|
|
1185
|
+
>
|
|
1186
|
+
<div class="searchstax-facet-title">
|
|
1187
|
+
{{ facet.label }}
|
|
762
1188
|
</div>
|
|
763
|
-
<div class="searchstax-
|
|
1189
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
1190
|
+
</div>
|
|
1191
|
+
<div
|
|
1192
|
+
class="searchstax-facet-values-container"
|
|
1193
|
+
aria-live="polite"
|
|
1194
|
+
>
|
|
1195
|
+
<div
|
|
1196
|
+
*ngFor="let facetValue of facetValues(facet); index as key"
|
|
1197
|
+
class="searchstax-facet-value-container"
|
|
1198
|
+
[class]="{
|
|
1199
|
+
'searchstax-facet-value-disabled': facetValue.disabled
|
|
1200
|
+
}"
|
|
1201
|
+
#ref
|
|
1202
|
+
>
|
|
1203
|
+
<div class="searchstax-facet-input">
|
|
1204
|
+
<input
|
|
1205
|
+
type="checkbox"
|
|
1206
|
+
class="searchstax-facet-input-checkbox"
|
|
1207
|
+
[checked]="isChecked(facetValue, context)"
|
|
1208
|
+
[attr.aria-label]="
|
|
1209
|
+
facetValue.value + ' ' + facetValue.count
|
|
1210
|
+
"
|
|
1211
|
+
[disabled]="facetValue.disabled"
|
|
1212
|
+
(click)="
|
|
1213
|
+
selectFacet(ref, $event, facetValue, true, context)
|
|
1214
|
+
"
|
|
1215
|
+
/>
|
|
1216
|
+
</div>
|
|
1217
|
+
<div
|
|
1218
|
+
class="searchstax-facet-value-label"
|
|
1219
|
+
(click)="
|
|
1220
|
+
selectFacet(ref, $event, facetValue, false, context)
|
|
1221
|
+
"
|
|
1222
|
+
>
|
|
1223
|
+
{{ facetValue.value }}
|
|
1224
|
+
</div>
|
|
764
1225
|
<div
|
|
765
|
-
class="searchstax-
|
|
766
|
-
|
|
767
|
-
|
|
1226
|
+
class="searchstax-facet-value-count"
|
|
1227
|
+
(click)="
|
|
1228
|
+
selectFacet(ref, $event, facetValue, false, context)
|
|
1229
|
+
"
|
|
768
1230
|
>
|
|
769
|
-
|
|
770
|
-
<div class="searchstax-facets-pill-icon-close"></div>
|
|
1231
|
+
({{ facetValue.count }})
|
|
771
1232
|
</div>
|
|
772
1233
|
</div>
|
|
773
1234
|
<div
|
|
774
|
-
class="searchstax-
|
|
775
|
-
*ngIf="
|
|
776
|
-
(click)="unselectAll(context)"
|
|
1235
|
+
class="searchstax-facet-show-more-container"
|
|
1236
|
+
*ngIf="facet.hasMoreFacets"
|
|
777
1237
|
>
|
|
778
|
-
<div class="searchstax-facets-pill-label">Clear Filters</div>
|
|
779
|
-
</div>
|
|
780
|
-
</div>
|
|
781
|
-
<div
|
|
782
|
-
class="searchstax-facets-mobile-overlay"
|
|
783
|
-
[class]="{ 'searchstax-show': facetMobileData(facetsTemplateDataMobile)?.overlayOpened }"
|
|
784
|
-
>
|
|
785
|
-
<div class="searchstax-facets-mobile-overlay-header">
|
|
786
|
-
<div class="searchstax-facets-mobile-overlay-header-title">Filter By</div>
|
|
787
|
-
<div class="searchstax-search-close" (click)="closeOverlay(context)"></div>
|
|
788
|
-
</div>
|
|
789
|
-
<div class="searchstax-facets-container-mobile">
|
|
790
1238
|
<div
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1239
|
+
class="searchstax-facet-show-more-container"
|
|
1240
|
+
(click)="showMoreLessMobile($event, facet, context)"
|
|
1241
|
+
(keyup.enter)="showMoreLessMobile($event, facet, context)"
|
|
1242
|
+
(keyup.space)="showMoreLessMobile($event, facet, context)"
|
|
1243
|
+
tabindex="0"
|
|
794
1244
|
>
|
|
795
|
-
<div
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
>
|
|
807
|
-
<div class="searchstax-facet-input">
|
|
808
|
-
<input
|
|
809
|
-
type="checkbox"
|
|
810
|
-
class="searchstax-facet-input-checkbox"
|
|
811
|
-
[checked]="isChecked(facetValue, context)"
|
|
812
|
-
[disabled]="facetValue.disabled"
|
|
813
|
-
(click)="selectFacet(ref, $event, facetValue, true, context)"
|
|
814
|
-
/>
|
|
815
|
-
</div>
|
|
816
|
-
<div
|
|
817
|
-
class="searchstax-facet-value-label"
|
|
818
|
-
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
819
|
-
>
|
|
820
|
-
{{ facetValue.value }}
|
|
821
|
-
</div>
|
|
822
|
-
<div
|
|
823
|
-
class="searchstax-facet-value-count"
|
|
824
|
-
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
825
|
-
>
|
|
826
|
-
({{ facetValue.count }})
|
|
827
|
-
</div>
|
|
828
|
-
</div>
|
|
829
|
-
<div class="searchstax-facet-show-more-container" *ngIf="facet.hasMoreFacets">
|
|
830
|
-
<div
|
|
831
|
-
class="searchstax-facet-show-more-container"
|
|
832
|
-
(click)="showMoreLessDesktop($event, facet, context)"
|
|
833
|
-
>
|
|
834
|
-
<div
|
|
835
|
-
*ngIf="facet.showingAllFacets"
|
|
836
|
-
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
837
|
-
>
|
|
838
|
-
less
|
|
839
|
-
</div>
|
|
840
|
-
<div
|
|
841
|
-
*ngIf="!facet.showingAllFacets"
|
|
842
|
-
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
843
|
-
>
|
|
844
|
-
more
|
|
845
|
-
</div>
|
|
846
|
-
</div>
|
|
847
|
-
</div>
|
|
848
|
-
</div>
|
|
1245
|
+
<div
|
|
1246
|
+
*ngIf="facet.showingAllFacets"
|
|
1247
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
1248
|
+
>
|
|
1249
|
+
less
|
|
1250
|
+
</div>
|
|
1251
|
+
<div
|
|
1252
|
+
*ngIf="!facet.showingAllFacets"
|
|
1253
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
1254
|
+
>
|
|
1255
|
+
more
|
|
849
1256
|
</div>
|
|
850
1257
|
</div>
|
|
851
1258
|
</div>
|
|
852
|
-
<button class="searchstax-facets-mobile-overlay-done" (click)="closeOverlay(context)">Done</button>
|
|
853
1259
|
</div>
|
|
854
1260
|
</div>
|
|
855
|
-
</
|
|
1261
|
+
</div>
|
|
1262
|
+
</div>
|
|
1263
|
+
<button
|
|
1264
|
+
class="searchstax-facets-mobile-overlay-done"
|
|
1265
|
+
(click)="closeOverlay(context)"
|
|
1266
|
+
>
|
|
1267
|
+
Done
|
|
1268
|
+
</button>
|
|
1269
|
+
</div>
|
|
1270
|
+
</div>
|
|
1271
|
+
</ng-template>
|
|
856
1272
|
</app-searchstax-search-facets>
|
|
857
1273
|
```
|
|
858
1274
|
|
|
859
1275
|
### SearchFeedback Widget ###
|
|
860
1276
|
|
|
861
|
-
|
|
1277
|
+
The SearchStax Site Search solution includes an Angular feedback widget for your custom search page.
|
|
1278
|
+
|
|
1279
|
+
The SearchstaxFeedbackWidget for Angular displays search feedback and stats.
|
|
1280
|
+
|
|
1281
|
+
**Usage**
|
|
1282
|
+
|
|
862
1283
|
```
|
|
863
1284
|
<app-searchstax-search-feedback></app-searchstax-search-feedback>
|
|
864
1285
|
```
|
|
865
1286
|
|
|
1287
|
+
**Main Template Override**
|
|
1288
|
+
|
|
1289
|
+
Main template for the search feedback message.
|
|
1290
|
+
|
|
1291
|
+
It receives following props:
|
|
1292
|
+
- searchFeedbackData - Feedback data object
|
|
1293
|
+
- onOriginalQueryClick - Handler for clicking on original query suggestion
|
|
866
1294
|
|
|
867
|
-
|
|
1295
|
+
**Example**
|
|
868
1296
|
```
|
|
869
1297
|
<app-searchstax-search-feedback [templateOverride]="feedbackTemplate">
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
1298
|
+
<ng-template
|
|
1299
|
+
#feedbackTemplate
|
|
1300
|
+
let-searchFeedbackData="searchFeedbackData"
|
|
1301
|
+
let-onOriginalQueryClick="onOriginalQueryClick"
|
|
1302
|
+
let-context="context"
|
|
1303
|
+
>
|
|
1304
|
+
<h2 class="searchstax-feedback-container">
|
|
1305
|
+
Showing
|
|
1306
|
+
<b
|
|
1307
|
+
>{{ searchFeedbackData!.startResultIndex }} -
|
|
1308
|
+
{{ searchFeedbackData!.endResultIndex }}</b
|
|
1309
|
+
>
|
|
1310
|
+
of <b>{{ searchFeedbackData!.totalResults }}</b> results
|
|
1311
|
+
<span *ngIf="searchFeedbackData.searchTerm"
|
|
1312
|
+
>for "<b>{{ searchFeedbackData!.searchTerm }}</b
|
|
1313
|
+
>"
|
|
1314
|
+
</span>
|
|
1315
|
+
<div class="searchstax-feedback-container-suggested">
|
|
1316
|
+
<div *ngIf="searchFeedbackData.autoCorrectedQuery">
|
|
1317
|
+
Search instead for
|
|
1318
|
+
<a
|
|
1319
|
+
href="#"
|
|
1320
|
+
(click)="onOriginalQueryClick($event, context)"
|
|
1321
|
+
class="searchstax-feedback-original-query"
|
|
1322
|
+
[attr.aria-label]="
|
|
1323
|
+
'Search instead for: ' + searchFeedbackData!.originalQuery
|
|
1324
|
+
"
|
|
1325
|
+
>{{ searchFeedbackData!.originalQuery }}</a
|
|
1326
|
+
>
|
|
1327
|
+
</div>
|
|
1328
|
+
</div>
|
|
1329
|
+
</h2>
|
|
1330
|
+
</ng-template>
|
|
1331
|
+
</app-searchstax-search-feedback>
|
|
898
1332
|
```
|
|
899
1333
|
|
|
900
|
-
|
|
1334
|
+
### RelatedSearches widget ###
|
|
901
1335
|
|
|
1336
|
+
The SearchStax Site Search solution offers an Angular related-searches widget for your custom search page.
|
|
902
1337
|
|
|
1338
|
+
The SearchstaxRelatedSearchesWidget displays related searches.
|
|
903
1339
|
|
|
904
|
-
|
|
1340
|
+
**Usage**
|
|
905
1341
|
```
|
|
906
|
-
<app-searchstax-related-searches
|
|
1342
|
+
<app-searchstax-related-searches
|
|
907
1343
|
[relatedSearchesURL]="config.relatedSearchesURL"
|
|
908
1344
|
[relatedSearchesAPIKey]="config.relatedSearchesAPIKey"
|
|
909
1345
|
></app-searchstax-related-searches>
|
|
910
1346
|
```
|
|
911
1347
|
|
|
1348
|
+
**Props**
|
|
1349
|
+
|
|
1350
|
+
- relatedSearchesURL: API URL for fetching related searches
|
|
1351
|
+
- relatedSearchesAPIKey?: API key for related searches API
|
|
1352
|
+
|
|
1353
|
+
**Main Template Override**
|
|
1354
|
+
|
|
1355
|
+
Main template for related searches.
|
|
1356
|
+
|
|
1357
|
+
It receives following props:
|
|
1358
|
+
|
|
1359
|
+
- relatedData - Related searches data object
|
|
1360
|
+
- executeSearch - Handler to run new search from related term
|
|
1361
|
+
|
|
1362
|
+
**Example**
|
|
912
1363
|
|
|
913
|
-
example of search RelatedSearches widget initialization with template overrides
|
|
914
1364
|
```
|
|
915
|
-
|
|
1365
|
+
<app-searchstax-related-searches
|
|
916
1366
|
[relatedSearchesURL]="config.relatedSearchesURL"
|
|
917
1367
|
[relatedSearchesAPIKey]="config.relatedSearchesAPIKey"
|
|
918
1368
|
[templateOverride]="relatedTemplate"
|
|
919
1369
|
>
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1370
|
+
<ng-template
|
|
1371
|
+
#relatedTemplate
|
|
1372
|
+
let-rand="rand"
|
|
1373
|
+
let-relatedData="relatedData"
|
|
1374
|
+
let-executeSearch="executeSearch"
|
|
1375
|
+
let-context="context"
|
|
1376
|
+
>
|
|
1377
|
+
<div
|
|
1378
|
+
class="searchstax-related-searches-container"
|
|
1379
|
+
[id]="'searchstax-related-searches-container' + rand"
|
|
1380
|
+
>
|
|
1381
|
+
Related searches: <span id="searchstax-related-searches"></span>
|
|
1382
|
+
<span
|
|
1383
|
+
class="searchstax-related-search"
|
|
1384
|
+
*ngIf="relatedData.relatedSearches"
|
|
1385
|
+
>
|
|
1386
|
+
<span
|
|
1387
|
+
*ngFor="let related of relatedData.relatedSearches"
|
|
1388
|
+
(click)="executeSearch(related, context)"
|
|
1389
|
+
(keyup.enter)="executeSearch(related, context)"
|
|
1390
|
+
(keyup.space)="executeSearch(related, context)"
|
|
1391
|
+
tabindex="0"
|
|
1392
|
+
class="searchstax-related-search searchstax-related-search-item"
|
|
1393
|
+
[attr.aria-label]="'Related search: ' + related.related_search"
|
|
1394
|
+
>
|
|
1395
|
+
{{ related.related_search }}<span *ngIf="!related.last">,</span>
|
|
1396
|
+
</span>
|
|
1397
|
+
</span>
|
|
1398
|
+
</div>
|
|
1399
|
+
</ng-template>
|
|
1400
|
+
</app-searchstax-related-searches>
|
|
941
1401
|
```
|
|
942
1402
|
|
|
943
1403
|
### ExternalPromotions widget ###
|
|
944
1404
|
|
|
945
|
-
|
|
1405
|
+
The SearchStax Site Search solution offers an Angular external-promotions widget for your custom search page.
|
|
1406
|
+
|
|
1407
|
+
The SearchstaxExternalPromotionsWidget displays external promotions fetched from the API.
|
|
1408
|
+
|
|
1409
|
+
**Usage**
|
|
1410
|
+
|
|
946
1411
|
```
|
|
947
1412
|
<app-searchstax-external-promotions></app-searchstax-external-promotions>
|
|
948
1413
|
```
|
|
949
1414
|
|
|
1415
|
+
**Main Template Override**
|
|
1416
|
+
|
|
1417
|
+
Main template for external promotions.
|
|
950
1418
|
|
|
951
|
-
|
|
1419
|
+
It receives following props:
|
|
1420
|
+
|
|
1421
|
+
- externalPromotionsData – External promotions data object
|
|
1422
|
+
- trackClick – Handler for tracking link clicks
|
|
1423
|
+
|
|
1424
|
+
**Example**
|
|
952
1425
|
```
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
1426
|
+
<app-searchstax-external-promotions [templateOverride]="externalPromotionsTemplate">
|
|
1427
|
+
<ng-template
|
|
1428
|
+
#externalPromotionsTemplate
|
|
1429
|
+
let-context="context"
|
|
1430
|
+
let-externalPromotionsData="externalPromotionsData"
|
|
1431
|
+
let-trackClick="trackClick"
|
|
1432
|
+
>
|
|
1433
|
+
<div
|
|
1434
|
+
class="searchstax-external-promotions-container"
|
|
1435
|
+
id="searchstax-external-promotions-container"
|
|
1436
|
+
>
|
|
1437
|
+
<div
|
|
1438
|
+
class="searchstax-external-promotion searchstax-search-result"
|
|
1439
|
+
*ngFor="
|
|
1440
|
+
let externalPromotion of externalPromotionsData.externalPromotions
|
|
1441
|
+
"
|
|
1442
|
+
>
|
|
1443
|
+
<div class="icon-elevated"></div>
|
|
1444
|
+
<a
|
|
1445
|
+
*ngIf="externalPromotion.url"
|
|
1446
|
+
[href]="externalPromotion.url"
|
|
1447
|
+
(click)="trackClick(externalPromotion, $event, context)"
|
|
1448
|
+
class="searchstax-result-item-link"
|
|
1449
|
+
></a>
|
|
1450
|
+
<div class="searchstax-search-result-title-container">
|
|
1451
|
+
<span class="searchstax-search-result-title">{{
|
|
1452
|
+
externalPromotion.name
|
|
1453
|
+
}}</span>
|
|
1454
|
+
</div>
|
|
1455
|
+
<p
|
|
1456
|
+
*ngIf="externalPromotion.description"
|
|
1457
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
1458
|
+
>
|
|
1459
|
+
{{ externalPromotion.description }}
|
|
1460
|
+
</p>
|
|
1461
|
+
<p
|
|
1462
|
+
*ngIf="externalPromotion.url"
|
|
1463
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
1464
|
+
>
|
|
1465
|
+
{{ externalPromotion.url }}
|
|
1466
|
+
</p>
|
|
1467
|
+
</div>
|
|
1468
|
+
</div>
|
|
1469
|
+
</ng-template>
|
|
990
1470
|
</app-searchstax-external-promotions>
|
|
991
1471
|
```
|
|
992
1472
|
|
|
993
1473
|
|
|
994
1474
|
### Sorting Widget ###
|
|
995
1475
|
|
|
996
|
-
|
|
1476
|
+
The SearchStax Site Search solution provides an Angular sorting widget for your custom search page.
|
|
1477
|
+
|
|
1478
|
+
The SearchstaxSortingWidget displays sorting options for search results.
|
|
1479
|
+
|
|
1480
|
+
**Usage**
|
|
1481
|
+
|
|
997
1482
|
```
|
|
998
1483
|
<app-searchstax-search-sorting></app-searchstax-search-sorting>
|
|
999
1484
|
```
|
|
1000
1485
|
|
|
1486
|
+
**Main Template Override**
|
|
1487
|
+
|
|
1488
|
+
Main template for sorting widget.
|
|
1489
|
+
|
|
1490
|
+
It receives following props:
|
|
1491
|
+
|
|
1492
|
+
- sortingData – Sorting data object
|
|
1493
|
+
- orderChange – Handler for sorting change
|
|
1494
|
+
- selectedSorting – Current selected sorting
|
|
1495
|
+
|
|
1496
|
+
**Example**
|
|
1001
1497
|
|
|
1002
|
-
example of sorting widget initialization with template override
|
|
1003
1498
|
```
|
|
1004
1499
|
<app-searchstax-search-sorting [templateOverride]="sortingTemplateOverride">
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1500
|
+
<ng-template
|
|
1501
|
+
#sortingTemplateOverride
|
|
1502
|
+
let-selectedSorting="selectedSorting"
|
|
1503
|
+
let-orderChange="orderChange"
|
|
1504
|
+
let-context="context"
|
|
1505
|
+
>
|
|
1506
|
+
<div class="searchstax-sorting-container">
|
|
1507
|
+
<label
|
|
1508
|
+
class="searchstax-sorting-label"
|
|
1509
|
+
for="searchstax-search-order-select"
|
|
1510
|
+
>Sort By</label
|
|
1511
|
+
>
|
|
1512
|
+
<select
|
|
1513
|
+
id="searchstax-search-order-select"
|
|
1514
|
+
class="searchstax-search-order-select"
|
|
1515
|
+
[(ngModel)]="context.selectedSorting"
|
|
1516
|
+
(change)="orderChange($event, context)"
|
|
1517
|
+
>
|
|
1518
|
+
<option
|
|
1519
|
+
*ngFor="let sortOption of context.sortingData.sortOptions"
|
|
1520
|
+
[value]="sortOption.key"
|
|
1010
1521
|
>
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
[value]="selectedSorting"
|
|
1017
|
-
(change)="orderChange($event, context)"
|
|
1018
|
-
>
|
|
1019
|
-
<option value="">Relevance</option>
|
|
1020
|
-
<option value="date desc">Newest Content</option>
|
|
1021
|
-
<option value="date asc">Oldest Content</option>
|
|
1022
|
-
</select>
|
|
1023
|
-
</div>
|
|
1024
|
-
</ng-template>
|
|
1522
|
+
{{ sortOption.value }}
|
|
1523
|
+
</option>
|
|
1524
|
+
</select>
|
|
1525
|
+
</div>
|
|
1526
|
+
</ng-template>
|
|
1025
1527
|
</app-searchstax-search-sorting>
|
|
1026
1528
|
```
|
|
1027
1529
|
|
|
1028
1530
|
|
|
1029
1531
|
## Template overrides
|
|
1030
|
-
Templates
|
|
1532
|
+
Templates use vue templating.
|
|
1031
1533
|
|
|
1032
1534
|
## STYLING
|
|
1033
1535
|
|
|
@@ -1039,4 +1541,4 @@ css can be taken from
|
|
|
1039
1541
|
|
|
1040
1542
|
```
|
|
1041
1543
|
./../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/mainTheme.css
|
|
1042
|
-
```
|
|
1544
|
+
```
|