@searchstax-inc/searchstudio-ux-angular 1.2.53 → 4.1.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 +16 -1
- package/README.md +1224 -687
- package/package.json +5 -2
- package/esm2022/lib/components/searchstax-input/searchstax-input.component.mjs +0 -115
- package/esm2022/lib/components/searchstax-results/searchstax-results.component.mjs +0 -83
- package/esm2022/lib/components/searchstax-search-answer/searchstax-search-answer.component.mjs +0 -46
- package/esm2022/lib/components/searchstax-search-external/searchstax-search-external.component.mjs +0 -40
- package/esm2022/lib/components/searchstax-search-facets/searchstax-search-facets.component.mjs +0 -112
- package/esm2022/lib/components/searchstax-search-location/searchstax-search-location.component.mjs +0 -92
- package/esm2022/lib/components/searchstax-search-overview/searchstax-search-overview.component.mjs +0 -41
- package/esm2022/lib/components/searchstax-search-pagination/searchstax-search-pagination.component.mjs +0 -62
- package/esm2022/lib/components/searchstax-search-related/searchstax-search-related.component.mjs +0 -44
- package/esm2022/lib/components/searchstax-search-sorting/searchstax-search-sorting.component.mjs +0 -46
- package/esm2022/lib/components/searchstax-wrapper.component.mjs +0 -93
- package/esm2022/lib/searchstudio-ux-angular.module.mjs +0 -73
- package/esm2022/lib/services/store-service.service.mjs +0 -17
- package/esm2022/public-api.mjs +0 -17
- package/esm2022/searchstax-inc-searchstudio-ux-angular.mjs +0 -5
- package/fesm2022/searchstax-inc-searchstudio-ux-angular.mjs +0 -818
- package/fesm2022/searchstax-inc-searchstudio-ux-angular.mjs.map +0 -1
- package/index.d.ts +0 -5
- package/lib/components/searchstax-input/searchstax-input.component.d.ts +0 -27
- package/lib/components/searchstax-results/searchstax-results.component.d.ts +0 -26
- package/lib/components/searchstax-search-answer/searchstax-search-answer.component.d.ts +0 -19
- package/lib/components/searchstax-search-external/searchstax-search-external.component.d.ts +0 -17
- package/lib/components/searchstax-search-facets/searchstax-search-facets.component.d.ts +0 -37
- package/lib/components/searchstax-search-location/searchstax-search-location.component.d.ts +0 -33
- package/lib/components/searchstax-search-overview/searchstax-search-overview.component.d.ts +0 -17
- package/lib/components/searchstax-search-pagination/searchstax-search-pagination.component.d.ts +0 -21
- package/lib/components/searchstax-search-related/searchstax-search-related.component.d.ts +0 -19
- package/lib/components/searchstax-search-sorting/searchstax-search-sorting.component.d.ts +0 -18
- package/lib/components/searchstax-wrapper.component.d.ts +0 -31
- package/lib/searchstudio-ux-angular.module.d.ts +0 -19
- package/lib/services/store-service.service.d.ts +0 -8
- package/public-api.d.ts +0 -13
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
|
-
<app-searchstax-answer [
|
|
163
|
+
<app-searchstax-answer [showMoreAfterWordCount]="100"></app-searchstax-answer>
|
|
161
164
|
```
|
|
162
165
|
|
|
166
|
+
**Props**
|
|
167
|
+
|
|
168
|
+
- showMoreAfterWordCount - 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 [
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
194
|
+
<app-searchstax-answer [showMoreAfterWordCount]="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
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
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>
|
|
224
|
+
</div>
|
|
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>
|
|
285
235
|
</div>
|
|
286
|
-
</
|
|
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
|
+
- templateOverride - template override. look at examples below
|
|
301
267
|
|
|
302
|
-
|
|
268
|
+
|
|
269
|
+
**inputWidgetTemplate**
|
|
270
|
+
|
|
271
|
+
The templateOverride prop allows customizing the input UI.
|
|
272
|
+
|
|
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,699 @@ 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
|
+
- locationValuesOverride - location widget values
|
|
457
|
+
- locationSearchEnabled - boolean stating if locationSearch is locationSearchEnabled
|
|
458
|
+
- templateOverride - template override. look at examples below
|
|
459
|
+
|
|
460
|
+
|
|
461
|
+
**Template Override**
|
|
462
|
+
|
|
463
|
+
The searchLocationTemplate prop allows customizing the location input UI.
|
|
464
|
+
|
|
465
|
+
It receives the following props:
|
|
466
|
+
|
|
467
|
+
- locationData – data containing info on when to show certain elements
|
|
468
|
+
- inputValue – value of location input
|
|
469
|
+
- locationBlur - Handler for location input blur
|
|
470
|
+
- radiusChange - Handler for location radius change
|
|
471
|
+
- selectValue - Value of radius select
|
|
472
|
+
- inputChange - location input change handler
|
|
473
|
+
- locationError - boolean stating if location has error
|
|
474
|
+
- getCurrentLocation - Handler for getting current location from browser
|
|
475
|
+
|
|
476
|
+
|
|
477
|
+
**Example**
|
|
478
|
+
|
|
377
479
|
```
|
|
480
|
+
const config = {
|
|
481
|
+
appId: "APP_ID",
|
|
482
|
+
relatedSearchesAPIKey: "KEY"
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
const locationWidgetConfig = {
|
|
486
|
+
locationDecode: (term: string): Promise<ISearchstaxLocation> => {
|
|
487
|
+
return new Promise((resolve) => {
|
|
488
|
+
// make a request to google geocoding API to retrieve lat, lon and address
|
|
489
|
+
|
|
490
|
+
const geocodingAPIKey = "GEOCODING_API_KEY";
|
|
491
|
+
const geocodingURL = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodeURIComponent(
|
|
492
|
+
term
|
|
493
|
+
)}&key=${geocodingAPIKey}`;
|
|
494
|
+
fetch(geocodingURL)
|
|
495
|
+
.then((response) => response.json())
|
|
496
|
+
.then((data) => {
|
|
497
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
498
|
+
const result = data.results[0];
|
|
499
|
+
const location = {
|
|
500
|
+
lat: result.geometry.location.lat,
|
|
501
|
+
lon: result.geometry.location.lng,
|
|
502
|
+
address: result.formatted_address,
|
|
503
|
+
};
|
|
504
|
+
resolve(location);
|
|
505
|
+
} else {
|
|
506
|
+
resolve({
|
|
507
|
+
address: undefined,
|
|
508
|
+
lat: undefined,
|
|
509
|
+
lon: undefined,
|
|
510
|
+
error: true,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
})
|
|
514
|
+
.catch(() => {
|
|
515
|
+
resolve({
|
|
516
|
+
address: undefined,
|
|
517
|
+
lat: undefined,
|
|
518
|
+
lon: undefined,
|
|
519
|
+
error: true,
|
|
520
|
+
});
|
|
521
|
+
});
|
|
522
|
+
});
|
|
523
|
+
},
|
|
524
|
+
locationDecodeCoordinatesToAddress: (lat: string, lon: string): Promise<ISearchstaxLocation> => {
|
|
525
|
+
return new Promise((resolve) => {
|
|
526
|
+
fetch(
|
|
527
|
+
`https://geocoding-staging.searchstax.co/reverse?location=${lat},${lon}&components=country:US&app_id=${config.appId}`,
|
|
528
|
+
{
|
|
529
|
+
method: "GET",
|
|
530
|
+
headers: {
|
|
531
|
+
Authorization: `Token ${config.relatedSearchesAPIKey}`,
|
|
532
|
+
},
|
|
533
|
+
}
|
|
534
|
+
)
|
|
535
|
+
.then((response) => response.json())
|
|
536
|
+
.then((data) => {
|
|
537
|
+
if (data.status === "OK" && data.results.length > 0) {
|
|
538
|
+
const result = data.results[0];
|
|
539
|
+
resolve({
|
|
540
|
+
address: result.formatted_address,
|
|
541
|
+
lat: lat,
|
|
542
|
+
lon: lon,
|
|
543
|
+
error: false,
|
|
544
|
+
});
|
|
545
|
+
} else {
|
|
546
|
+
resolve({
|
|
547
|
+
address: undefined,
|
|
548
|
+
lat: lat,
|
|
549
|
+
lon: lon,
|
|
550
|
+
error: true,
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
})
|
|
554
|
+
.catch(() => {
|
|
555
|
+
resolve({
|
|
556
|
+
address: undefined,
|
|
557
|
+
lat: lat,
|
|
558
|
+
lon: lon,
|
|
559
|
+
error: true,
|
|
560
|
+
});
|
|
561
|
+
});
|
|
562
|
+
});
|
|
563
|
+
},
|
|
564
|
+
locationSearchEnabled: false,
|
|
565
|
+
locationValuesOverride: {
|
|
566
|
+
locationDistanceEnabled: true,
|
|
567
|
+
filterValues: ["any", "1000"],
|
|
568
|
+
filterUnit: "miles",
|
|
569
|
+
locationFilterDefaultValue: "any"
|
|
570
|
+
},
|
|
571
|
+
}
|
|
378
572
|
<app-searchstax-search-location
|
|
379
|
-
[locationDecode]="locationDecode"
|
|
573
|
+
[locationDecode]="locationWidgetConfig.locationDecode"
|
|
574
|
+
[templateOverride]="locationTemplate"
|
|
575
|
+
[locationValuesOverride]="locationWidgetConfig.locationValuesOverride"
|
|
576
|
+
[locationSearchEnabled]="locationWidgetConfig.locationSearchEnabled"
|
|
577
|
+
[locationDecodeCoordinatesToAddress]="locationWidgetConfig.locationDecodeCoordinatesToAddress"
|
|
380
578
|
[templateOverride]="locationTemplate"
|
|
381
|
-
[locationDecodeCoordinatesToAddress]="locationDecodeCoordinatesToAddress"
|
|
382
579
|
>
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
580
|
+
<ng-template
|
|
581
|
+
#locationTemplate
|
|
582
|
+
let-context="context"
|
|
583
|
+
let-locationData="locationData"
|
|
584
|
+
let-inputValue="inputValue"
|
|
585
|
+
let-selectValue="selectValue"
|
|
586
|
+
let-radiusChange="radiusChange"
|
|
587
|
+
let-inputChange="inputChange"
|
|
588
|
+
let-locationBlur="locationBlur"
|
|
589
|
+
let-locationError="locationError"
|
|
590
|
+
let-getCurrentLocation="getCurrentLocation"
|
|
591
|
+
>
|
|
592
|
+
<div
|
|
593
|
+
class="searchstax-location-input-container"
|
|
594
|
+
data-test-id="searchstax-location-input-container"
|
|
595
|
+
*ngIf="locationData"
|
|
596
|
+
>
|
|
597
|
+
<div class="searchstax-location-input-wrapper">
|
|
598
|
+
<span class="searchstax-location-input-label">NEAR</span>
|
|
599
|
+
<div class="searchstax-location-input-wrapper-inner">
|
|
600
|
+
<input
|
|
601
|
+
type="text"
|
|
602
|
+
id="searchstax-location-input"
|
|
603
|
+
class="searchstax-location-input"
|
|
604
|
+
[ngClass]="{
|
|
605
|
+
'searchstax-input-location-error': locationError
|
|
606
|
+
}"
|
|
607
|
+
placeholder="Zip, Postal Code or City..."
|
|
608
|
+
aria-label="Search Location Input"
|
|
609
|
+
data-test-id="searchstax-location-input"
|
|
610
|
+
[value]="inputValue"
|
|
611
|
+
(change)="inputChange($event, context)"
|
|
612
|
+
(blur)="locationBlur(context)"
|
|
613
|
+
/>
|
|
614
|
+
<button
|
|
615
|
+
(click)="getCurrentLocation(context)"
|
|
616
|
+
class="searchstax-get-current-location-button"
|
|
394
617
|
>
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
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>
|
|
618
|
+
Use my current location
|
|
619
|
+
</button>
|
|
620
|
+
</div>
|
|
621
|
+
<span
|
|
622
|
+
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
623
|
+
class="searchstax-location-input-label"
|
|
624
|
+
>WITHIN</span
|
|
625
|
+
>
|
|
626
|
+
<select
|
|
627
|
+
*ngIf="locationData.shouldShowLocationDistanceDropdown"
|
|
628
|
+
id="searchstax-location-radius-select"
|
|
629
|
+
class="searchstax-location-radius-select"
|
|
630
|
+
aria-label="Search Location Radius Select"
|
|
631
|
+
data-test-id="searchstax-location-radius-select"
|
|
632
|
+
(change)="radiusChange($event, context)"
|
|
633
|
+
[(ngModel)]="context.selectValue"
|
|
634
|
+
>
|
|
635
|
+
<option
|
|
636
|
+
*ngFor="let value of locationData.locationSearchDistanceValues"
|
|
637
|
+
[value]="value.value"
|
|
638
|
+
>
|
|
639
|
+
{{ value.label }}
|
|
640
|
+
</option>
|
|
641
|
+
</select>
|
|
642
|
+
</div>
|
|
643
|
+
</div>
|
|
644
|
+
</ng-template>
|
|
645
|
+
|
|
450
646
|
</app-searchstax-search-location>
|
|
451
647
|
```
|
|
648
|
+
|
|
452
649
|
### Result Widget ###
|
|
453
650
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
```
|
|
651
|
+
The SearchStax Site Search solution offers an Angular results widget to assist with your custom search page.
|
|
652
|
+
|
|
653
|
+
The SearchstaxResultsWidget for Angular component displays the search results.
|
|
654
|
+
|
|
655
|
+
**Usage**
|
|
460
656
|
|
|
461
|
-
example of results widget initialization with minimum options and infinite scroll behavior
|
|
462
657
|
```
|
|
463
658
|
<app-searchstax-results
|
|
464
659
|
[afterLinkClick]="afterLinkClick"
|
|
465
|
-
[renderMethod]="'
|
|
660
|
+
[renderMethod]="'“pagination”'"
|
|
661
|
+
[resultsPerPage]="10"
|
|
466
662
|
></app-searchstax-results>
|
|
467
663
|
```
|
|
468
664
|
|
|
469
|
-
|
|
665
|
+
**Props**
|
|
666
|
+
|
|
667
|
+
- renderMethod – either “pagination” or “infiniteScroll”.
|
|
668
|
+
- resultsPerPage – number of results on a page.
|
|
669
|
+
- afterLinkClick – Callback function invoked when a result link is clicked. Allows modifying the result object.
|
|
670
|
+
- noResultTemplate - template override for no results view
|
|
671
|
+
- resultsTemplate - template override for result item
|
|
672
|
+
|
|
673
|
+
|
|
674
|
+
**Result Template Override**
|
|
675
|
+
|
|
676
|
+
The resultsTemplate prop allows customizing the result UI.
|
|
677
|
+
|
|
678
|
+
It receives following props:
|
|
679
|
+
- searchResults - Array of result items
|
|
680
|
+
- resultClicked - Handler for result click events
|
|
681
|
+
|
|
682
|
+
|
|
683
|
+
**No Results Template Override**
|
|
684
|
+
|
|
685
|
+
The noResultTemplate prop allows customizing the result UI.
|
|
686
|
+
|
|
687
|
+
It receives following props:
|
|
688
|
+
|
|
689
|
+
- searchResults - Array of result items
|
|
690
|
+
- resultClicked - Handler for result click events
|
|
691
|
+
- searchTerm - Search input term
|
|
692
|
+
- metadata - Metadata object
|
|
693
|
+
- executeSearch - Handler for executing srearch
|
|
694
|
+
- store - Main store of app
|
|
695
|
+
|
|
696
|
+
**Example of default render method**
|
|
470
697
|
```
|
|
471
698
|
<app-searchstax-results
|
|
472
699
|
[afterLinkClick]="afterLinkClick"
|
|
473
700
|
[resultsTemplate]="resultsTemplate"
|
|
474
701
|
[noResultsTemplate]="noResultsTemplate"
|
|
475
702
|
>
|
|
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
|
-
|
|
703
|
+
<ng-template
|
|
704
|
+
#resultsTemplate
|
|
705
|
+
let-searchResults="searchResults"
|
|
706
|
+
let-resultClicked="resultClicked"
|
|
707
|
+
let-isImage="isImage"
|
|
708
|
+
let-context="context"
|
|
709
|
+
>
|
|
710
|
+
<div class="searchstax-search-results">
|
|
711
|
+
<a
|
|
712
|
+
*ngFor="let searchResult of searchResults"
|
|
713
|
+
[href]="searchResult.url"
|
|
714
|
+
[attr.data-searchstax-unique-result-id]="searchResult.uniqueId"
|
|
715
|
+
(click)="resultClicked(searchResult, $event, context)"
|
|
716
|
+
(keyup.enter)="resultClicked(searchResult, $event, context)"
|
|
717
|
+
(keyup.space)="resultClicked(searchResult, $event, context)"
|
|
718
|
+
[attr.aria-labelledby]="'title-' + searchResult.uniqueId"
|
|
719
|
+
tabindex="0"
|
|
720
|
+
class="searchstax-result-item-link searchstax-result-item-link-wrapping"
|
|
721
|
+
>
|
|
722
|
+
<div
|
|
723
|
+
class="searchstax-search-result"
|
|
724
|
+
[ngClass]="{ 'has-thumbnail': searchResult.thumbnail }"
|
|
725
|
+
>
|
|
726
|
+
<div
|
|
727
|
+
*ngIf="searchResult.promoted"
|
|
728
|
+
class="searchstax-search-result-promoted"
|
|
729
|
+
></div>
|
|
730
|
+
<div
|
|
731
|
+
*ngIf="searchResult.ribbon"
|
|
732
|
+
[innerHTML]="searchResult.ribbon"
|
|
733
|
+
class="searchstax-search-result-ribbon"
|
|
734
|
+
></div>
|
|
735
|
+
<img
|
|
736
|
+
alt=""
|
|
737
|
+
*ngIf="searchResult.thumbnail"
|
|
738
|
+
[src]="searchResult.thumbnail"
|
|
739
|
+
class="searchstax-thumbnail"
|
|
740
|
+
/>
|
|
741
|
+
<div class="searchstax-search-result-title-container">
|
|
742
|
+
<span
|
|
743
|
+
class="searchstax-search-result-title"
|
|
744
|
+
[id]="'title-' + searchResult.uniqueId"
|
|
745
|
+
[innerHTML]="searchResult.title"
|
|
746
|
+
></span>
|
|
747
|
+
</div>
|
|
748
|
+
<p
|
|
749
|
+
*ngIf="searchResult.paths"
|
|
750
|
+
class="searchstax-search-result-common"
|
|
751
|
+
[innerHTML]="searchResult.paths"
|
|
752
|
+
></p>
|
|
753
|
+
<p
|
|
754
|
+
*ngIf="searchResult.description"
|
|
755
|
+
[innerHTML]="searchResult.description"
|
|
756
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
757
|
+
></p>
|
|
758
|
+
<div *ngFor="let unmappedField of searchResult.unmappedFields">
|
|
759
|
+
<div
|
|
760
|
+
*ngIf="isImage(unmappedField)"
|
|
761
|
+
class="searchstax-search-result-image-container"
|
|
762
|
+
>
|
|
763
|
+
<img
|
|
764
|
+
alt=""
|
|
765
|
+
[src]="unmappedField.value"
|
|
766
|
+
class="searchstax-result-image"
|
|
767
|
+
/>
|
|
536
768
|
</div>
|
|
537
|
-
<div>
|
|
538
|
-
<p
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
<p>Lost? Click on the ‘X” in the Search Box to reset your search.</p>
|
|
769
|
+
<div *ngIf="!isImage(unmappedField)">
|
|
770
|
+
<p
|
|
771
|
+
class="searchstax-search-result-common"
|
|
772
|
+
[innerHTML]="unmappedField.value"
|
|
773
|
+
></p>
|
|
543
774
|
</div>
|
|
544
|
-
</
|
|
775
|
+
</div>
|
|
776
|
+
</div>
|
|
777
|
+
</a>
|
|
778
|
+
</div>
|
|
779
|
+
</ng-template>
|
|
780
|
+
<ng-template
|
|
781
|
+
#noResultsTemplate
|
|
782
|
+
let-metadata="metadata"
|
|
783
|
+
let-searchTerm="searchTerm"
|
|
784
|
+
let-executeSearch="executeSearch"
|
|
785
|
+
let-context="context"
|
|
786
|
+
>
|
|
787
|
+
<div class="searchstax-no-results">
|
|
788
|
+
Showing <strong>no results</strong> for
|
|
789
|
+
<strong>"{{ searchTerm }}"</strong>
|
|
790
|
+
<br />
|
|
791
|
+
<span *ngIf="metadata?.spellingSuggestion"
|
|
792
|
+
> Did you mean
|
|
793
|
+
<a
|
|
794
|
+
href="#"
|
|
795
|
+
[attr.aria-label]="'did you mean: ' + metadata?.spellingSuggestion"
|
|
796
|
+
class="searchstax-suggestion-term"
|
|
797
|
+
(click)="
|
|
798
|
+
executeSearch(metadata?.spellingSuggestion ?? '', $event, context)
|
|
799
|
+
"
|
|
800
|
+
>{{ metadata?.spellingSuggestion }}</a
|
|
801
|
+
>?</span
|
|
802
|
+
>
|
|
803
|
+
</div>
|
|
804
|
+
<ul>
|
|
805
|
+
<li>
|
|
806
|
+
Try searching for search related terms or topics. We offer a wide
|
|
807
|
+
variety of content to help you get the information you need.
|
|
808
|
+
</li>
|
|
809
|
+
<li>Lost? Click on the ‘X” in the Search Box to reset your search.</li>
|
|
810
|
+
</ul>
|
|
811
|
+
</ng-template>
|
|
812
|
+
|
|
545
813
|
</app-searchstax-results>
|
|
546
814
|
```
|
|
547
815
|
|
|
816
|
+
**Example of infinite scroll and pagination render methods**
|
|
817
|
+
```
|
|
818
|
+
<app-searchstax-results
|
|
819
|
+
[afterLinkClick]="afterLinkClick"
|
|
820
|
+
[renderMethod]="'infiniteScroll'"
|
|
821
|
+
></app-searchstax-results>
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
```
|
|
825
|
+
|
|
548
826
|
### Pagination Widget ###
|
|
549
827
|
|
|
828
|
+
The SearchStax Site Search solution offers an Angular pagination widget to assist with you custom search page.
|
|
829
|
+
|
|
830
|
+
The SearchstaxPaginationWidget for Angular displays pagination controls for search results.
|
|
831
|
+
|
|
832
|
+
**Usage**
|
|
550
833
|
|
|
551
|
-
example of pagination widget initialization with minimum options
|
|
552
834
|
```
|
|
553
835
|
<app-searchstax-search-pagination></app-searchstax-search-pagination>
|
|
554
836
|
```
|
|
555
837
|
|
|
556
|
-
|
|
838
|
+
**Props**
|
|
839
|
+
|
|
840
|
+
- infiniteScrollTemplateOverride - template override for infinite scroll view pagination
|
|
841
|
+
- templateOverride - template override for standard view pagination
|
|
842
|
+
|
|
843
|
+
**Main Template Override**
|
|
844
|
+
|
|
845
|
+
Main template for the pagination controls.
|
|
846
|
+
|
|
847
|
+
It receives following props:
|
|
848
|
+
|
|
849
|
+
- paginationData – Pagination info object
|
|
850
|
+
- previousPage – Handler for previous page click
|
|
851
|
+
- nextPage - – Handler for next page click
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
**Infinite Scroll Template Override**
|
|
855
|
+
|
|
856
|
+
Main template for the pagination controls in infinite scroll mode.
|
|
857
|
+
|
|
858
|
+
It receives following props:
|
|
859
|
+
- isLastPage - boolean, true if its last page
|
|
860
|
+
- results - results.length can be used if there are results
|
|
861
|
+
|
|
862
|
+
**Example**
|
|
863
|
+
|
|
557
864
|
```
|
|
558
865
|
<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
|
-
|
|
866
|
+
<ng-template
|
|
867
|
+
#paginationTemplate
|
|
868
|
+
let-paginationData="paginationData"
|
|
869
|
+
let-previousPage="previousPage"
|
|
870
|
+
let-nextPage="nextPage"
|
|
871
|
+
let-context="context"
|
|
872
|
+
>
|
|
873
|
+
<div class="searchstax-pagination-container">
|
|
874
|
+
<div class="searchstax-pagination-content">
|
|
875
|
+
<a
|
|
876
|
+
class="searchstax-pagination-previous"
|
|
877
|
+
[class]="paginationData.isFirstPage ? 'disabled' : ''"
|
|
878
|
+
(click)="previousPage($event, context)"
|
|
879
|
+
(keyup.enter)="previousPage($event, context)"
|
|
880
|
+
(keyup.space)="previousPage($event, context)"
|
|
881
|
+
tabindex="0"
|
|
882
|
+
id="searchstax-pagination-previous"
|
|
883
|
+
>
|
|
884
|
+
< Previous
|
|
885
|
+
</a>
|
|
886
|
+
<div class="searchstax-pagination-details">
|
|
887
|
+
{{ paginationData?.startResultIndex }} -
|
|
888
|
+
{{ paginationData?.endResultIndex }} of
|
|
889
|
+
{{ paginationData?.totalResults }}
|
|
890
|
+
</div>
|
|
891
|
+
<a
|
|
892
|
+
class="searchstax-pagination-next"
|
|
893
|
+
[class]="paginationData.isLastPage ? 'disabled' : ''"
|
|
894
|
+
(click)="nextPage($event, context)"
|
|
895
|
+
(keyup.enter)="nextPage($event, context)"
|
|
896
|
+
(keyup.space)="nextPage($event, context)"
|
|
897
|
+
tabindex="0"
|
|
898
|
+
id="searchstax-pagination-next"
|
|
899
|
+
>Next ></a
|
|
900
|
+
>
|
|
901
|
+
</div>
|
|
902
|
+
</div>
|
|
903
|
+
</ng-template>
|
|
904
|
+
</app-searchstax-search-pagination>
|
|
905
|
+
|
|
906
|
+
// infinite scroll example
|
|
590
907
|
|
|
591
|
-
example of pagination widget with infinite scroll
|
|
592
|
-
```
|
|
593
908
|
<app-searchstax-search-pagination [templateOverride]="paginationTemplate"
|
|
594
909
|
[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
|
-
|
|
910
|
+
<ng-template
|
|
911
|
+
#infiniteScrollTemplate
|
|
912
|
+
let-paginationData="paginationData"
|
|
913
|
+
let-nextPage="nextPage"
|
|
914
|
+
let-context="context"
|
|
915
|
+
>
|
|
916
|
+
<div class="searchstax-pagination-container">
|
|
917
|
+
<div class="searchstax-pagination-content">
|
|
918
|
+
<a
|
|
919
|
+
class="searchstax-pagination-load-more"
|
|
920
|
+
(click)="nextPage($event, context)"
|
|
921
|
+
(keyup.enter)="nextPage($event, context)"
|
|
922
|
+
(keyup.space)="nextPage($event, context)"
|
|
923
|
+
tabindex="0"
|
|
924
|
+
>
|
|
925
|
+
Load More
|
|
926
|
+
</a>
|
|
927
|
+
</div>
|
|
928
|
+
</div>
|
|
929
|
+
</ng-template>
|
|
930
|
+
<ng-template
|
|
931
|
+
#paginationTemplate
|
|
932
|
+
let-paginationData="paginationData"
|
|
933
|
+
let-previousPage="previousPage"
|
|
934
|
+
let-nextPage="nextPage"
|
|
935
|
+
let-context="context"
|
|
936
|
+
>
|
|
937
|
+
<div class="searchstax-pagination-container">
|
|
938
|
+
<div class="searchstax-pagination-content">
|
|
939
|
+
<a
|
|
940
|
+
class="searchstax-pagination-previous"
|
|
941
|
+
[class]="paginationData.isFirstPage ? 'disabled' : ''"
|
|
942
|
+
(click)="previousPage($event, context)"
|
|
943
|
+
(keyup.enter)="previousPage($event, context)"
|
|
944
|
+
(keyup.space)="previousPage($event, context)"
|
|
945
|
+
tabindex="0"
|
|
946
|
+
id="searchstax-pagination-previous"
|
|
947
|
+
>
|
|
948
|
+
< Previous
|
|
949
|
+
</a>
|
|
950
|
+
<div class="searchstax-pagination-details">
|
|
951
|
+
{{ paginationData?.startResultIndex }} -
|
|
952
|
+
{{ paginationData?.endResultIndex }} of
|
|
953
|
+
{{ paginationData?.totalResults }}
|
|
954
|
+
</div>
|
|
955
|
+
<a
|
|
956
|
+
class="searchstax-pagination-next"
|
|
957
|
+
[class]="paginationData.isLastPage ? 'disabled' : ''"
|
|
958
|
+
(click)="nextPage($event, context)"
|
|
959
|
+
(keyup.enter)="nextPage($event, context)"
|
|
960
|
+
(keyup.space)="nextPage($event, context)"
|
|
961
|
+
tabindex="0"
|
|
962
|
+
id="searchstax-pagination-next"
|
|
963
|
+
>Next ></a
|
|
964
|
+
>
|
|
965
|
+
</div>
|
|
966
|
+
</div>
|
|
967
|
+
</ng-template>
|
|
642
968
|
</app-searchstax-search-pagination>
|
|
643
969
|
```
|
|
644
970
|
|
|
645
971
|
### Facets Widget ###
|
|
646
972
|
|
|
647
|
-
|
|
973
|
+
The SearchStax Site Search solution offers the SearchstaxFacetsWidget for Angular to display the search facets.
|
|
974
|
+
|
|
975
|
+
**Facet Selection and Order**
|
|
976
|
+
|
|
977
|
+
Facet lists are configured and ordered on the Site Search [Faceting Tab](https://www.searchstax.com/docs/searchstudio/faceting-tab/).
|
|
978
|
+
|
|
979
|
+
**Usage**
|
|
980
|
+
|
|
648
981
|
```
|
|
649
982
|
<app-searchstax-search-facets
|
|
650
983
|
[facetingType]="'showUnavailable'"
|
|
@@ -653,8 +986,52 @@ example of facets widget initialization with minimum options
|
|
|
653
986
|
></app-searchstax-search-facets>
|
|
654
987
|
```
|
|
655
988
|
|
|
989
|
+
**Props**
|
|
990
|
+
|
|
991
|
+
- facetingType: "and" | "or" | "showUnavailable" | "tabs"; // type that determines how facets will behave
|
|
992
|
+
- specificFacets?: string[]; // optional array of facet names that if provided will only render those facets
|
|
993
|
+
- itemsPerPageDesktop: number; // default expanded facets for desktop
|
|
994
|
+
- itemsPerPageMobile: number; // default expanded facets for mobile
|
|
995
|
+
- templateOverrideMobile - template override for mobile view
|
|
996
|
+
- templateOverrideDesktop - template override for desktop view
|
|
997
|
+
|
|
998
|
+
|
|
999
|
+
**Main Template Desktop Override**
|
|
1000
|
+
|
|
1001
|
+
Main wrapper template for desktop facets display.
|
|
1002
|
+
|
|
1003
|
+
It receives following props:
|
|
1004
|
+
- facetsTemplateDataDesktop - Facets data object
|
|
1005
|
+
- isNotDeactivated - Check if facet group is active
|
|
1006
|
+
- toggleFacetGroup - Toggle facet group active state
|
|
1007
|
+
- isChecked - Check if facet value is selected
|
|
1008
|
+
- selectFacet - Handler for facet select
|
|
1009
|
+
- showMoreLessDesktop - Show more/less facets handler
|
|
1010
|
+
- facetContainers - Object of facet DOM containers
|
|
1011
|
+
- updateRefDesktop - Handler for keeping checkbox references
|
|
656
1012
|
|
|
657
|
-
|
|
1013
|
+
|
|
1014
|
+
**Main Template Mobile Override**
|
|
1015
|
+
|
|
1016
|
+
Main wrapper template for mobile facets display.
|
|
1017
|
+
|
|
1018
|
+
It receives following props:
|
|
1019
|
+
- facetsTemplateDataMobile - Facets data object
|
|
1020
|
+
- selectedFacetsCheckboxes - Selected facet values
|
|
1021
|
+
- isNotDeactivated - Check if facet group is active
|
|
1022
|
+
- toggleFacetGroup - Toggle facet group active state
|
|
1023
|
+
- isChecked - Check if facet value is selected
|
|
1024
|
+
- selectFacet - Handler for facet select
|
|
1025
|
+
- showMoreLessDesktop - Show more/less facets handler
|
|
1026
|
+
- facetContainers - Object of facet DOM containers
|
|
1027
|
+
- openOverlay - Handler to open mobile overlay
|
|
1028
|
+
- unselectFacet - Handler to unselect specific facet
|
|
1029
|
+
- unselectAll - Handler to unselect all facets
|
|
1030
|
+
- closeOverlay - Handler to close mobile overlay
|
|
1031
|
+
- updateRefMobile - Handler for keeping mobile checkbox references
|
|
1032
|
+
|
|
1033
|
+
|
|
1034
|
+
**Example**
|
|
658
1035
|
```
|
|
659
1036
|
<app-searchstax-search-facets
|
|
660
1037
|
[facetingType]="'showUnavailable'"
|
|
@@ -663,371 +1040,531 @@ example of facets widget initialization with template overrides
|
|
|
663
1040
|
[templateOverrideDesktop]="templateOverrideDesktop"
|
|
664
1041
|
[templateOverrideMobile]="templateOverrideMobile"
|
|
665
1042
|
>
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
1043
|
+
<ng-template
|
|
1044
|
+
#templateOverrideDesktop
|
|
1045
|
+
let-facetsTemplateDataDesktop="facetsTemplateDataDesktop"
|
|
1046
|
+
let-isNotDeactivated="isNotDeactivated"
|
|
1047
|
+
let-context="context"
|
|
1048
|
+
let-toggleFacetGroup="toggleFacetGroup"
|
|
1049
|
+
let-facetValues="facetValues"
|
|
1050
|
+
let-isChecked="isChecked"
|
|
1051
|
+
let-selectFacet="selectFacet"
|
|
1052
|
+
let-showMoreLessDesktop="showMoreLessDesktop"
|
|
1053
|
+
>
|
|
1054
|
+
<div class="searchstax-facets-container-desktop">
|
|
1055
|
+
<div
|
|
1056
|
+
class="searchstax-facet-container"
|
|
1057
|
+
*ngFor="let facet of facetsTemplateDataDesktop?.facets"
|
|
1058
|
+
[class]="{ active: isNotDeactivated(facet.name, context) }"
|
|
1059
|
+
>
|
|
1060
|
+
<div>
|
|
1061
|
+
<div
|
|
1062
|
+
class="searchstax-facet-title-container"
|
|
1063
|
+
(click)="toggleFacetGroup(facet.name, context)"
|
|
676
1064
|
>
|
|
677
|
-
<div class="searchstax-
|
|
1065
|
+
<div class="searchstax-facet-title">
|
|
1066
|
+
{{ facet.label }}
|
|
1067
|
+
</div>
|
|
1068
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
1069
|
+
</div>
|
|
1070
|
+
<div class="searchstax-facet-values-container" aria-live="polite">
|
|
1071
|
+
<div
|
|
1072
|
+
*ngFor="let facetValue of facetValues(facet); index as key"
|
|
1073
|
+
class="searchstax-facet-value-container"
|
|
1074
|
+
[class]="{
|
|
1075
|
+
'searchstax-facet-value-disabled': facetValue.disabled
|
|
1076
|
+
}"
|
|
1077
|
+
#ref
|
|
1078
|
+
>
|
|
1079
|
+
<div class="searchstax-facet-input">
|
|
1080
|
+
<input
|
|
1081
|
+
type="checkbox"
|
|
1082
|
+
class="searchstax-facet-input-checkbox"
|
|
1083
|
+
[checked]="isChecked(facetValue, context)"
|
|
1084
|
+
[attr.aria-label]="
|
|
1085
|
+
facetValue.value + ' ' + facetValue.count
|
|
1086
|
+
"
|
|
1087
|
+
[disabled]="facetValue.disabled"
|
|
1088
|
+
(click)="
|
|
1089
|
+
selectFacet(ref, $event, facetValue, true, context)
|
|
1090
|
+
"
|
|
1091
|
+
/>
|
|
1092
|
+
</div>
|
|
678
1093
|
<div
|
|
679
|
-
class="searchstax-facet-
|
|
680
|
-
|
|
681
|
-
[class]="{ active: isNotDeactivated(facet.name, context) }"
|
|
1094
|
+
class="searchstax-facet-value-label"
|
|
1095
|
+
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
682
1096
|
>
|
|
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>
|
|
1097
|
+
{{ facetValue.value }}
|
|
1098
|
+
</div>
|
|
1099
|
+
<div
|
|
1100
|
+
class="searchstax-facet-value-count"
|
|
1101
|
+
(click)="selectFacet(ref, $event, facetValue, false, context)"
|
|
1102
|
+
>
|
|
1103
|
+
({{ facetValue.count }})
|
|
1104
|
+
</div>
|
|
1105
|
+
</div>
|
|
1106
|
+
<div
|
|
1107
|
+
class="searchstax-facet-show-more-container"
|
|
1108
|
+
*ngIf="facet.hasMoreFacets"
|
|
1109
|
+
>
|
|
1110
|
+
<div
|
|
1111
|
+
class="searchstax-facet-show-more-container"
|
|
1112
|
+
(click)="showMoreLessDesktop($event, facet, context)"
|
|
1113
|
+
(keyup.enter)="showMoreLessDesktop($event, facet, context)"
|
|
1114
|
+
(keyup.space)="showMoreLessDesktop($event, facet, context)"
|
|
1115
|
+
tabindex="0"
|
|
1116
|
+
>
|
|
1117
|
+
<div
|
|
1118
|
+
*ngIf="facet.showingAllFacets"
|
|
1119
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
1120
|
+
>
|
|
1121
|
+
less
|
|
1122
|
+
</div>
|
|
1123
|
+
<div
|
|
1124
|
+
*ngIf="!facet.showingAllFacets"
|
|
1125
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
1126
|
+
>
|
|
1127
|
+
more
|
|
737
1128
|
</div>
|
|
738
1129
|
</div>
|
|
739
1130
|
</div>
|
|
740
|
-
</
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
1131
|
+
</div>
|
|
1132
|
+
</div>
|
|
1133
|
+
</div>
|
|
1134
|
+
</div>
|
|
1135
|
+
</ng-template>
|
|
1136
|
+
<ng-template
|
|
1137
|
+
#templateOverrideMobile
|
|
1138
|
+
let-isNotDeactivated="isNotDeactivated"
|
|
1139
|
+
let-context="context"
|
|
1140
|
+
let-toggleFacetGroup="toggleFacetGroup"
|
|
1141
|
+
let-facetValues="facetValues"
|
|
1142
|
+
let-isChecked="isChecked"
|
|
1143
|
+
let-selectFacet="selectFacet"
|
|
1144
|
+
let-openOverlay="openOverlay"
|
|
1145
|
+
let-selectedFacetsCheckboxes="selectedFacetsCheckboxes"
|
|
1146
|
+
let-unselectFacet="unselectFacet"
|
|
1147
|
+
let-unselectAll="unselectAll"
|
|
1148
|
+
let-facetMobileData="facetMobileData"
|
|
1149
|
+
let-facetsTemplateDataMobile="facetsTemplateDataMobile"
|
|
1150
|
+
let-closeOverlay="closeOverlay"
|
|
1151
|
+
let-showMoreLessDesktop="showMoreLessDesktop"
|
|
1152
|
+
let-showMoreLessMobile="showMoreLessMobile"
|
|
1153
|
+
>
|
|
1154
|
+
<div class="searchstax-facets-container-mobile">
|
|
1155
|
+
<div class="searchstax-facets-pills-container">
|
|
1156
|
+
<div
|
|
1157
|
+
class="searchstax-facets-pill searchstax-facets-pill-filter-by"
|
|
1158
|
+
(click)="openOverlay(context)"
|
|
1159
|
+
>
|
|
1160
|
+
<div class="searchstax-facets-pill-label">Filter By</div>
|
|
1161
|
+
</div>
|
|
1162
|
+
<div class="searchstax-facets-pills-selected">
|
|
1163
|
+
<div
|
|
1164
|
+
class="searchstax-facets-pill searchstax-facets-pill-facets"
|
|
1165
|
+
*ngFor="let facet of selectedFacetsCheckboxes"
|
|
1166
|
+
(click)="unselectFacet(facet, context)"
|
|
1167
|
+
>
|
|
1168
|
+
<div class="searchstax-facets-pill-label">
|
|
1169
|
+
{{ facet.value }} ({{ facet.count }})
|
|
1170
|
+
</div>
|
|
1171
|
+
<div class="searchstax-facets-pill-icon-close"></div>
|
|
1172
|
+
</div>
|
|
1173
|
+
</div>
|
|
1174
|
+
<div
|
|
1175
|
+
class="searchstax-facets-pill searchstax-clear-filters searchstax-facets-pill-clear-all"
|
|
1176
|
+
*ngIf="selectedFacetsCheckboxes.length"
|
|
1177
|
+
(click)="unselectAll(context)"
|
|
1178
|
+
>
|
|
1179
|
+
<div class="searchstax-facets-pill-label">Clear Filters</div>
|
|
1180
|
+
</div>
|
|
1181
|
+
</div>
|
|
1182
|
+
<div
|
|
1183
|
+
class="searchstax-facets-mobile-overlay"
|
|
1184
|
+
[class]="{
|
|
1185
|
+
'searchstax-show': facetMobileData(facetsTemplateDataMobile)
|
|
1186
|
+
?.overlayOpened
|
|
1187
|
+
}"
|
|
1188
|
+
>
|
|
1189
|
+
<div class="searchstax-facets-mobile-overlay-header">
|
|
1190
|
+
<div class="searchstax-facets-mobile-overlay-header-title">
|
|
1191
|
+
Filter By
|
|
1192
|
+
</div>
|
|
1193
|
+
<div
|
|
1194
|
+
class="searchstax-search-close"
|
|
1195
|
+
(click)="closeOverlay(context)"
|
|
1196
|
+
></div>
|
|
1197
|
+
</div>
|
|
1198
|
+
<div class="searchstax-facets-container-mobile">
|
|
1199
|
+
<div
|
|
1200
|
+
*ngFor="let facet of facetsTemplateDataMobile?.facets"
|
|
1201
|
+
class="searchstax-facet-container"
|
|
1202
|
+
[class]="{
|
|
1203
|
+
active: isNotDeactivated(facet.name, context)
|
|
1204
|
+
}"
|
|
757
1205
|
>
|
|
758
|
-
<div
|
|
759
|
-
<div
|
|
760
|
-
|
|
761
|
-
|
|
1206
|
+
<div>
|
|
1207
|
+
<div
|
|
1208
|
+
class="searchstax-facet-title-container"
|
|
1209
|
+
(click)="toggleFacetGroup(facet.name, context)"
|
|
1210
|
+
>
|
|
1211
|
+
<div class="searchstax-facet-title">
|
|
1212
|
+
{{ facet.label }}
|
|
762
1213
|
</div>
|
|
763
|
-
<div class="searchstax-
|
|
1214
|
+
<div class="searchstax-facet-title-arrow active"></div>
|
|
1215
|
+
</div>
|
|
1216
|
+
<div
|
|
1217
|
+
class="searchstax-facet-values-container"
|
|
1218
|
+
aria-live="polite"
|
|
1219
|
+
>
|
|
1220
|
+
<div
|
|
1221
|
+
*ngFor="let facetValue of facetValues(facet); index as key"
|
|
1222
|
+
class="searchstax-facet-value-container"
|
|
1223
|
+
[class]="{
|
|
1224
|
+
'searchstax-facet-value-disabled': facetValue.disabled
|
|
1225
|
+
}"
|
|
1226
|
+
#ref
|
|
1227
|
+
>
|
|
1228
|
+
<div class="searchstax-facet-input">
|
|
1229
|
+
<input
|
|
1230
|
+
type="checkbox"
|
|
1231
|
+
class="searchstax-facet-input-checkbox"
|
|
1232
|
+
[checked]="isChecked(facetValue, context)"
|
|
1233
|
+
[attr.aria-label]="
|
|
1234
|
+
facetValue.value + ' ' + facetValue.count
|
|
1235
|
+
"
|
|
1236
|
+
[disabled]="facetValue.disabled"
|
|
1237
|
+
(click)="
|
|
1238
|
+
selectFacet(ref, $event, facetValue, true, context)
|
|
1239
|
+
"
|
|
1240
|
+
/>
|
|
1241
|
+
</div>
|
|
1242
|
+
<div
|
|
1243
|
+
class="searchstax-facet-value-label"
|
|
1244
|
+
(click)="
|
|
1245
|
+
selectFacet(ref, $event, facetValue, false, context)
|
|
1246
|
+
"
|
|
1247
|
+
>
|
|
1248
|
+
{{ facetValue.value }}
|
|
1249
|
+
</div>
|
|
764
1250
|
<div
|
|
765
|
-
class="searchstax-
|
|
766
|
-
|
|
767
|
-
|
|
1251
|
+
class="searchstax-facet-value-count"
|
|
1252
|
+
(click)="
|
|
1253
|
+
selectFacet(ref, $event, facetValue, false, context)
|
|
1254
|
+
"
|
|
768
1255
|
>
|
|
769
|
-
|
|
770
|
-
<div class="searchstax-facets-pill-icon-close"></div>
|
|
1256
|
+
({{ facetValue.count }})
|
|
771
1257
|
</div>
|
|
772
1258
|
</div>
|
|
773
1259
|
<div
|
|
774
|
-
class="searchstax-
|
|
775
|
-
*ngIf="
|
|
776
|
-
(click)="unselectAll(context)"
|
|
1260
|
+
class="searchstax-facet-show-more-container"
|
|
1261
|
+
*ngIf="facet.hasMoreFacets"
|
|
777
1262
|
>
|
|
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
1263
|
<div
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
1264
|
+
class="searchstax-facet-show-more-container"
|
|
1265
|
+
(click)="showMoreLessMobile($event, facet, context)"
|
|
1266
|
+
(keyup.enter)="showMoreLessMobile($event, facet, context)"
|
|
1267
|
+
(keyup.space)="showMoreLessMobile($event, facet, context)"
|
|
1268
|
+
tabindex="0"
|
|
794
1269
|
>
|
|
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>
|
|
1270
|
+
<div
|
|
1271
|
+
*ngIf="facet.showingAllFacets"
|
|
1272
|
+
class="searchstax-facet-show-less-button searchstax-facet-show-button"
|
|
1273
|
+
>
|
|
1274
|
+
less
|
|
1275
|
+
</div>
|
|
1276
|
+
<div
|
|
1277
|
+
*ngIf="!facet.showingAllFacets"
|
|
1278
|
+
class="searchstax-facet-show-more-button searchstax-facet-show-button"
|
|
1279
|
+
>
|
|
1280
|
+
more
|
|
849
1281
|
</div>
|
|
850
1282
|
</div>
|
|
851
1283
|
</div>
|
|
852
|
-
<button class="searchstax-facets-mobile-overlay-done" (click)="closeOverlay(context)">Done</button>
|
|
853
1284
|
</div>
|
|
854
1285
|
</div>
|
|
855
|
-
</
|
|
1286
|
+
</div>
|
|
1287
|
+
</div>
|
|
1288
|
+
<button
|
|
1289
|
+
class="searchstax-facets-mobile-overlay-done"
|
|
1290
|
+
(click)="closeOverlay(context)"
|
|
1291
|
+
>
|
|
1292
|
+
Done
|
|
1293
|
+
</button>
|
|
1294
|
+
</div>
|
|
1295
|
+
</div>
|
|
1296
|
+
</ng-template>
|
|
856
1297
|
</app-searchstax-search-facets>
|
|
857
1298
|
```
|
|
858
1299
|
|
|
859
1300
|
### SearchFeedback Widget ###
|
|
860
1301
|
|
|
861
|
-
|
|
1302
|
+
The SearchStax Site Search solution includes an Angular feedback widget for your custom search page.
|
|
1303
|
+
|
|
1304
|
+
The SearchstaxFeedbackWidget for Angular displays search feedback and stats.
|
|
1305
|
+
|
|
1306
|
+
**Usage**
|
|
1307
|
+
|
|
862
1308
|
```
|
|
863
1309
|
<app-searchstax-search-feedback></app-searchstax-search-feedback>
|
|
864
1310
|
```
|
|
865
1311
|
|
|
1312
|
+
**Props**
|
|
1313
|
+
|
|
1314
|
+
- templateOverride - template override for search feedback
|
|
1315
|
+
|
|
1316
|
+
**Main Template Override**
|
|
1317
|
+
|
|
1318
|
+
Main template for the search feedback message.
|
|
866
1319
|
|
|
867
|
-
|
|
1320
|
+
It receives following props:
|
|
1321
|
+
- searchFeedbackData - Feedback data object
|
|
1322
|
+
- onOriginalQueryClick - Handler for clicking on original query suggestion
|
|
1323
|
+
|
|
1324
|
+
**Example**
|
|
868
1325
|
```
|
|
869
1326
|
<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
|
-
|
|
1327
|
+
<ng-template
|
|
1328
|
+
#feedbackTemplate
|
|
1329
|
+
let-searchFeedbackData="searchFeedbackData"
|
|
1330
|
+
let-onOriginalQueryClick="onOriginalQueryClick"
|
|
1331
|
+
let-context="context"
|
|
1332
|
+
>
|
|
1333
|
+
<h2 class="searchstax-feedback-container">
|
|
1334
|
+
Showing
|
|
1335
|
+
<b
|
|
1336
|
+
>{{ searchFeedbackData!.startResultIndex }} -
|
|
1337
|
+
{{ searchFeedbackData!.endResultIndex }}</b
|
|
1338
|
+
>
|
|
1339
|
+
of <b>{{ searchFeedbackData!.totalResults }}</b> results
|
|
1340
|
+
<span *ngIf="searchFeedbackData.searchTerm"
|
|
1341
|
+
>for "<b>{{ searchFeedbackData!.searchTerm }}</b
|
|
1342
|
+
>"
|
|
1343
|
+
</span>
|
|
1344
|
+
<div class="searchstax-feedback-container-suggested">
|
|
1345
|
+
<div *ngIf="searchFeedbackData.autoCorrectedQuery">
|
|
1346
|
+
Search instead for
|
|
1347
|
+
<a
|
|
1348
|
+
href="#"
|
|
1349
|
+
(click)="onOriginalQueryClick($event, context)"
|
|
1350
|
+
class="searchstax-feedback-original-query"
|
|
1351
|
+
[attr.aria-label]="
|
|
1352
|
+
'Search instead for: ' + searchFeedbackData!.originalQuery
|
|
1353
|
+
"
|
|
1354
|
+
>{{ searchFeedbackData!.originalQuery }}</a
|
|
1355
|
+
>
|
|
1356
|
+
</div>
|
|
1357
|
+
</div>
|
|
1358
|
+
</h2>
|
|
1359
|
+
</ng-template>
|
|
1360
|
+
</app-searchstax-search-feedback>
|
|
898
1361
|
```
|
|
899
1362
|
|
|
900
|
-
|
|
1363
|
+
### RelatedSearches widget ###
|
|
901
1364
|
|
|
1365
|
+
The SearchStax Site Search solution offers an Angular related-searches widget for your custom search page.
|
|
902
1366
|
|
|
1367
|
+
The SearchstaxRelatedSearchesWidget displays related searches.
|
|
903
1368
|
|
|
904
|
-
|
|
1369
|
+
**Usage**
|
|
905
1370
|
```
|
|
906
|
-
<app-searchstax-related-searches
|
|
1371
|
+
<app-searchstax-related-searches
|
|
907
1372
|
[relatedSearchesURL]="config.relatedSearchesURL"
|
|
908
1373
|
[relatedSearchesAPIKey]="config.relatedSearchesAPIKey"
|
|
909
1374
|
></app-searchstax-related-searches>
|
|
910
1375
|
```
|
|
911
1376
|
|
|
1377
|
+
**Props**
|
|
1378
|
+
|
|
1379
|
+
- relatedSearchesURL: API URL for fetching related searches
|
|
1380
|
+
- relatedSearchesAPIKey?: API key for related searches API
|
|
1381
|
+
- templateOverride - template override for related search
|
|
1382
|
+
|
|
1383
|
+
**Main Template Override**
|
|
1384
|
+
|
|
1385
|
+
Main template for related searches.
|
|
1386
|
+
|
|
1387
|
+
It receives following props:
|
|
1388
|
+
|
|
1389
|
+
- relatedData - Related searches data object
|
|
1390
|
+
- executeSearch - Handler to run new search from related term
|
|
1391
|
+
|
|
1392
|
+
**Example**
|
|
912
1393
|
|
|
913
|
-
example of search RelatedSearches widget initialization with template overrides
|
|
914
1394
|
```
|
|
915
|
-
|
|
1395
|
+
<app-searchstax-related-searches
|
|
916
1396
|
[relatedSearchesURL]="config.relatedSearchesURL"
|
|
917
1397
|
[relatedSearchesAPIKey]="config.relatedSearchesAPIKey"
|
|
918
1398
|
[templateOverride]="relatedTemplate"
|
|
919
1399
|
>
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
1400
|
+
<ng-template
|
|
1401
|
+
#relatedTemplate
|
|
1402
|
+
let-rand="rand"
|
|
1403
|
+
let-relatedData="relatedData"
|
|
1404
|
+
let-executeSearch="executeSearch"
|
|
1405
|
+
let-context="context"
|
|
1406
|
+
>
|
|
1407
|
+
<div
|
|
1408
|
+
class="searchstax-related-searches-container"
|
|
1409
|
+
[id]="'searchstax-related-searches-container' + rand"
|
|
1410
|
+
>
|
|
1411
|
+
Related searches: <span id="searchstax-related-searches"></span>
|
|
1412
|
+
<span
|
|
1413
|
+
class="searchstax-related-search"
|
|
1414
|
+
*ngIf="relatedData.relatedSearches"
|
|
1415
|
+
>
|
|
1416
|
+
<span
|
|
1417
|
+
*ngFor="let related of relatedData.relatedSearches"
|
|
1418
|
+
(click)="executeSearch(related, context)"
|
|
1419
|
+
(keyup.enter)="executeSearch(related, context)"
|
|
1420
|
+
(keyup.space)="executeSearch(related, context)"
|
|
1421
|
+
tabindex="0"
|
|
1422
|
+
class="searchstax-related-search searchstax-related-search-item"
|
|
1423
|
+
[attr.aria-label]="'Related search: ' + related.related_search"
|
|
1424
|
+
>
|
|
1425
|
+
{{ related.related_search }}<span *ngIf="!related.last">,</span>
|
|
1426
|
+
</span>
|
|
1427
|
+
</span>
|
|
1428
|
+
</div>
|
|
1429
|
+
</ng-template>
|
|
1430
|
+
</app-searchstax-related-searches>
|
|
941
1431
|
```
|
|
942
1432
|
|
|
943
1433
|
### ExternalPromotions widget ###
|
|
944
1434
|
|
|
945
|
-
|
|
1435
|
+
The SearchStax Site Search solution offers an Angular external-promotions widget for your custom search page.
|
|
1436
|
+
|
|
1437
|
+
The SearchstaxExternalPromotionsWidget displays external promotions fetched from the API.
|
|
1438
|
+
|
|
1439
|
+
**Usage**
|
|
1440
|
+
|
|
946
1441
|
```
|
|
947
1442
|
<app-searchstax-external-promotions></app-searchstax-external-promotions>
|
|
948
1443
|
```
|
|
949
1444
|
|
|
1445
|
+
**Props**
|
|
1446
|
+
|
|
1447
|
+
- templateOverride - template override for external promotion
|
|
1448
|
+
|
|
1449
|
+
**Main Template Override**
|
|
1450
|
+
|
|
1451
|
+
Main template for external promotions.
|
|
1452
|
+
|
|
1453
|
+
It receives following props:
|
|
1454
|
+
|
|
1455
|
+
- externalPromotionsData – External promotions data object
|
|
1456
|
+
- trackClick – Handler for tracking link clicks
|
|
950
1457
|
|
|
951
|
-
|
|
1458
|
+
**Example**
|
|
952
1459
|
```
|
|
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
|
-
|
|
1460
|
+
<app-searchstax-external-promotions [templateOverride]="externalPromotionsTemplate">
|
|
1461
|
+
<ng-template
|
|
1462
|
+
#externalPromotionsTemplate
|
|
1463
|
+
let-context="context"
|
|
1464
|
+
let-externalPromotionsData="externalPromotionsData"
|
|
1465
|
+
let-trackClick="trackClick"
|
|
1466
|
+
>
|
|
1467
|
+
<div
|
|
1468
|
+
class="searchstax-external-promotions-container"
|
|
1469
|
+
id="searchstax-external-promotions-container"
|
|
1470
|
+
>
|
|
1471
|
+
<div
|
|
1472
|
+
class="searchstax-external-promotion searchstax-search-result"
|
|
1473
|
+
*ngFor="
|
|
1474
|
+
let externalPromotion of externalPromotionsData.externalPromotions
|
|
1475
|
+
"
|
|
1476
|
+
>
|
|
1477
|
+
<div class="icon-elevated"></div>
|
|
1478
|
+
<a
|
|
1479
|
+
*ngIf="externalPromotion.url"
|
|
1480
|
+
[href]="externalPromotion.url"
|
|
1481
|
+
(click)="trackClick(externalPromotion, $event, context)"
|
|
1482
|
+
class="searchstax-result-item-link"
|
|
1483
|
+
></a>
|
|
1484
|
+
<div class="searchstax-search-result-title-container">
|
|
1485
|
+
<span class="searchstax-search-result-title">{{
|
|
1486
|
+
externalPromotion.name
|
|
1487
|
+
}}</span>
|
|
1488
|
+
</div>
|
|
1489
|
+
<p
|
|
1490
|
+
*ngIf="externalPromotion.description"
|
|
1491
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
1492
|
+
>
|
|
1493
|
+
{{ externalPromotion.description }}
|
|
1494
|
+
</p>
|
|
1495
|
+
<p
|
|
1496
|
+
*ngIf="externalPromotion.url"
|
|
1497
|
+
class="searchstax-search-result-description searchstax-search-result-common"
|
|
1498
|
+
>
|
|
1499
|
+
{{ externalPromotion.url }}
|
|
1500
|
+
</p>
|
|
1501
|
+
</div>
|
|
1502
|
+
</div>
|
|
1503
|
+
</ng-template>
|
|
990
1504
|
</app-searchstax-external-promotions>
|
|
991
1505
|
```
|
|
992
1506
|
|
|
993
1507
|
|
|
994
1508
|
### Sorting Widget ###
|
|
995
1509
|
|
|
996
|
-
|
|
1510
|
+
The SearchStax Site Search solution provides an Angular sorting widget for your custom search page.
|
|
1511
|
+
|
|
1512
|
+
The SearchstaxSortingWidget displays sorting options for search results.
|
|
1513
|
+
|
|
1514
|
+
**Usage**
|
|
1515
|
+
|
|
997
1516
|
```
|
|
998
1517
|
<app-searchstax-search-sorting></app-searchstax-search-sorting>
|
|
999
1518
|
```
|
|
1000
1519
|
|
|
1520
|
+
**Main Template Override**
|
|
1521
|
+
|
|
1522
|
+
Main template for sorting widget.
|
|
1523
|
+
|
|
1524
|
+
It receives following props:
|
|
1525
|
+
|
|
1526
|
+
- sortingData – Sorting data object
|
|
1527
|
+
- orderChange – Handler for sorting change
|
|
1528
|
+
- selectedSorting – Current selected sorting
|
|
1529
|
+
- templateOverride - template override for sorting widget
|
|
1530
|
+
|
|
1531
|
+
**Example**
|
|
1001
1532
|
|
|
1002
|
-
example of sorting widget initialization with template override
|
|
1003
1533
|
```
|
|
1004
1534
|
<app-searchstax-search-sorting [templateOverride]="sortingTemplateOverride">
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1535
|
+
<ng-template
|
|
1536
|
+
#sortingTemplateOverride
|
|
1537
|
+
let-selectedSorting="selectedSorting"
|
|
1538
|
+
let-orderChange="orderChange"
|
|
1539
|
+
let-context="context"
|
|
1540
|
+
>
|
|
1541
|
+
<div class="searchstax-sorting-container">
|
|
1542
|
+
<label
|
|
1543
|
+
class="searchstax-sorting-label"
|
|
1544
|
+
for="searchstax-search-order-select"
|
|
1545
|
+
>Sort By</label
|
|
1546
|
+
>
|
|
1547
|
+
<select
|
|
1548
|
+
id="searchstax-search-order-select"
|
|
1549
|
+
class="searchstax-search-order-select"
|
|
1550
|
+
[(ngModel)]="context.selectedSorting"
|
|
1551
|
+
(change)="orderChange($event, context)"
|
|
1552
|
+
>
|
|
1553
|
+
<option
|
|
1554
|
+
*ngFor="let sortOption of context.sortingData.sortOptions"
|
|
1555
|
+
[value]="sortOption.key"
|
|
1010
1556
|
>
|
|
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>
|
|
1557
|
+
{{ sortOption.value }}
|
|
1558
|
+
</option>
|
|
1559
|
+
</select>
|
|
1560
|
+
</div>
|
|
1561
|
+
</ng-template>
|
|
1025
1562
|
</app-searchstax-search-sorting>
|
|
1026
1563
|
```
|
|
1027
1564
|
|
|
1028
1565
|
|
|
1029
1566
|
## Template overrides
|
|
1030
|
-
Templates
|
|
1567
|
+
Templates use vue templating.
|
|
1031
1568
|
|
|
1032
1569
|
## STYLING
|
|
1033
1570
|
|
|
@@ -1039,4 +1576,4 @@ css can be taken from
|
|
|
1039
1576
|
|
|
1040
1577
|
```
|
|
1041
1578
|
./../node_modules/@searchstax-inc/searchstudio-ux-js/dist/styles/mainTheme.css
|
|
1042
|
-
```
|
|
1579
|
+
```
|