instantsearch.widgets.infiniteHits({ container: string|HTMLElement, // Optional parameters escapeHTML: boolean, showPrevious: boolean, templates: object, cssClasses: object, transformItems: function, });
About this widget #
The infiniteHits
widget is used to display a list of results with a “Show more” button.
To configure the number of hits to show, use the hitsPerPage
widget or the configure
widget.
Examples #
1
2
3
4
5
6
7
8
9
10
11
instantsearch.widgets.infiniteHits({
container: '#infinite-hits',
templates: {
item: `
<h2>
{{#helpers.highlight}}{ "attribute": "name" }{{/helpers.highlight}}
</h2>
<p>{{ description }}</p>
`,
},
});
Options #
container
# |
type: string|HTMLElement
Required
The CSS Selector or |
||
|
|||
escapeHTML
# |
type: boolean
default: true
Optional
Escapes HTML entities from hits string values. |
||
|
|||
showPrevious
# |
type: boolean
default: false
Optional
Enable the button to load previous results. The button is only displayed if the routing option is enabled in |
||
|
|||
templates
# |
type: object
Optional
The templates to use for the widget. |
||
|
|||
cssClasses
# |
type: object
default: {}
Optional
The CSS classes to override.
|
||
Edit
Copy
|
|||
transformItems
# |
type: function
default: x => x
Optional
Receives the items, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them. |
||
Edit
Copy
|
Templates #
empty
# |
type: string|function
Optional
The template to use when there are no results. It exposes the |
||
Edit
Copy
|
|||
item
# |
type: string|function
Optional
The template to use for each result. This template receives an object containing a single record. The record has a new property |
||
Edit
Copy
|
|||
showPreviousText
# |
type: string|function
default: Show previous results
Optional
The template to use for the “Show previous” label. |
||
Edit
Copy
|
|||
showMoreText
# |
type: string|function
default: Show more results
Optional
The template to use for the “Show more” label. |
||
Edit
Copy
|
Customize the UI - connectInfiniteHits#
If you want to create your own UI of the infiniteHits
widget, you can use connectors.
It’s a 3-step process:
// 1. Create a render function
const renderInfiniteHits = (renderOptions, isFirstRender) => {
// Rendering logic
};
// 2. Create the custom widget
const customInfiniteHits = instantsearch.connectors.connectInfiniteHits(
renderInfiniteHits
);
// 3. Instantiate
search.addWidget(
customInfiniteHits({
// instance params
})
);
Create a render function#
This rendering function is called before the first search (init
lifecycle step)
and each time results come back from Algolia (render
lifecycle step).
const renderInfiniteHits = (renderOptions, isFirstRender) => {
const {
object[] hits,
object results,
boolean isFirstPage,
boolean isLastPage,
function showPrevious,
function showMore,
object widgetParams,
} = renderOptions;
if (isFirstRender) {
// Do some initial rendering and bind events
}
// Render the widget
}
Rendering options #
hits
# |
type: object[]
The matched hits from the Algolia API. You can leverage the highlighting feature of Algolia through the |
||
Copy
|
|||
results
# |
type: object
The complete response from the Algolia API. It contains the |
||
Copy
|
|||
isFirstPage
# |
type: boolean
Indicates whether the first page of hits has been reached. |
||
Copy
|
|||
isLastPage
# |
type: boolean
Indicates whether the last page of hits has been reached. |
||
Copy
|
|||
showPrevious
# |
type: function
Loads the previous page of hits. |
||
Copy
|
|||
showMore
# |
type: function
Loads the next page of hits. |
||
Copy
|
|||
widgetParams
# |
type: object
All original widget options forwarded to the render function. |
||
Copy
|
Create and instantiate the custom widget#
We first create custom widgets from our rendering function, then we instantiate them. When doing that, there are two types of parameters you can give:
- Instance parameters: they are predefined parameters that you can use to configure the behavior of Algolia.
- Your own parameters: to make the custom widget generic.
Both instance and custom parameters are available in connector.widgetParams
, inside the renderFunction
.
const customInfiniteHits = instantsearch.connectors.connectInfiniteHits(
renderInfiniteHits
);
search.addWidget(
customInfiniteHits({
// Optional parameters
escapeHTML: boolean,
showPrevious: boolean,
transformItems: function,
})
);
Instance options #
escapeHTML
# |
type: boolean
default: true
Optional
Escapes HTML entities from hits string values. |
||
|
|||
showPrevious
# |
type: boolean
default: false
Optional
Enable the button to load previous results. |
||
|
|||
transformItems
# |
type: function
default: x => x
Optional
Receives the items, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them. |
||
Edit
Copy
|
Full example#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Create the render function
const renderInfiniteHits = (renderOptions, isFirstRender) => {
const {
hits,
widgetParams,
showPrevious,
isFirstPage,
showMore,
isLastPage,
} = renderOptions;
if (isFirstRender) {
const ul = document.createElement('ul');
const previousButton = document.createElement('button');
previousButton.className = 'previous-button';
previousButton.textContent = 'Show previous';
previousButton.addEventListener('click', () => {
showPrevious();
});
const nextButton = document.createElement('button');
nextButton.className = 'next-button';
nextButton.textContent = 'Show more';
nextButton.addEventListener('click', () => {
showMore();
});
widgetParams.container.appendChild(previousButton);
widgetParams.container.appendChild(ul);
widgetParams.container.appendChild(nextButton);
return;
}
widgetParams.container.querySelector('.previous-button').disabled = isFirstPage;
widgetParams.container.querySelector('.next-button').disabled = isLastPage;
widgetParams.container.querySelector('ul').innerHTML = `
${hits
.map(
item =>
`<li>
${instantsearch.highlight({ attribute: 'name', hit: item })}
</li>`
)
.join('')}
`;
};
// Create the custom widget
const customInfiniteHits = instantsearch.connectors.connectInfiniteHits(
renderInfiniteHits
);
// Instantiate the custom widget
search.addWidget(
customInfiniteHits({
container: document.querySelector('#infinite-hits'),
showPrevious: true,
})
);
Sending Click and Conversion events#
InstantSearch can connect with the insights Javascript Client to allow sending click and conversion events right from the infiniteHits
widget.
Requirements#
This requires installing the search-insights
library separately:
You can refer to our insights documentation for more details.
It’s a 3-step process:
1. Install the Insights API client for JavaScript#
1
2
3
4
5
6
7
8
9
10
11
12
13
<script>
var ALGOLIA_INSIGHTS_SRC = "https://cdn.jsdelivr.net/npm/search-insights@1.1.1";
!function(e,a,t,n,s,i,c){e.AlgoliaAnalyticsObject=s,e.aa=e.aa||function(){
(e.aa.queue=e.aa.queue||[]).push(arguments)},i=a.createElement(t),c=a.getElementsByTagName(t)[0],
i.async=1,i.src=ALGOLIA_INSIGHTS_SRC,c.parentNode.insertBefore(i,c)
}(window,document,"script",0,"aa");
aa('init', {
appId: 'AJ0P3S7DWQ',
apiKey: '90dfaaf5755e694f341fe68f6e41a6d4',
});
</script>
2. Connect the Insights API client for JavaScript with InstantSearch and enable clickAnalytics
#
1
2
3
4
5
6
7
8
9
10
const search = instantsearch({
// ...
insightsClient: window.aa
});
search.addWidget(
instantsearch.widgets.configure({
clickAnalytics: true,
})
);
3. Call the insights function from your infiniteHits
component#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
search.addWidget(
instantsearch.widgets.infinitehits({
// ...
templates: {
item(hit) {
return `
<a href="/product.html?queryID=${hit.__queryID}">
<h2>${hit.name}</h2>
<button ${
instantsearch.insights('clickedObjectIDsAfterSearch', {
eventName: 'Add to favorite',
objectIDs: [hit.objectID]
})
}>
Add to favorite
</button>
</a>
`;
},
},
});
)
Provided props #
insights
# |
type: function
signature: (method: string, payload: object) => void
Sends insights events.
When not provided,
It is worth noting that
For more details on the constraints that apply to each |
||
Copy
|
Example#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
search.addWidget(
instantsearch.widgets.infiniteHits({
// ...
templates: {
item(hit) {
return `
<div>
<a href="/product.html?queryID=${hit.__queryID}">
<h2>${hit.name}</h2>
</a>
<button ${
instantsearch.insights('clickedObjectIDsAfterSearch', {
eventName: 'Add to favorite',
objectIDs: [hit.objectID]
})
}>
Add to favorite
</button>
</div>
`;
},
},
});
)
HTML output#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="ais-InfiniteHits">
<button class="ais-InfiniteHits-loadPrevious">
Show previous
</button>
<ol class="ais-InfiniteHits-list">
<li class="ais-InfiniteHits-item">
...
</li>
<li class="ais-InfiniteHits-item">
...
</li>
<li class="ais-InfiniteHits-item">
...
</li>
</ol>
<button class="ais-InfiniteHits-loadMore">
Show more
</button>
</div>