diff --git a/examples/js/getting-started/index.html b/examples/js/getting-started/index.html index 2140e545fd..6523ec514d 100644 --- a/examples/js/getting-started/index.html +++ b/examples/js/getting-started/index.html @@ -33,17 +33,14 @@

-
-
-
-
-
- -
- -
- -
+
+
+ +
+
+
+
+
diff --git a/examples/js/getting-started/src/app.js b/examples/js/getting-started/src/app.js index eb68272b0d..08c16ae3ee 100644 --- a/examples/js/getting-started/src/app.js +++ b/examples/js/getting-started/src/app.js @@ -1,12 +1,10 @@ import algoliasearch from 'algoliasearch/lite'; import instantsearch from 'instantsearch.js'; import { - configure, hits, - pagination, - panel, - refinementList, + index, searchBox, + refinementList, } from 'instantsearch.js/es/widgets'; const searchClient = algoliasearch( @@ -20,33 +18,37 @@ const search = instantsearch({ insights: true, }); +const itemComponent = (hit, { html, components }) => html` +
+

${components.ReverseHighlight({ hit, attribute: 'query' })}

+

${components.Highlight({ hit, attribute: 'description' })}

+
+`; + search.addWidgets([ - searchBox({ - container: '#searchbox', - }), + index({ + indexName: 'instant_search_demo_query_suggestions', + separate: true, + }).addWidgets([ + searchBox({ + container: '#searchbox', + }), + hits({ + container: '#hits', + templates: { + item: (hit, { html, components }) => html` + ${components.ReverseHighlight({ hit, attribute: 'query' })} + `, + }, + }), + ]), + refinementList({ container: '#filters', attribute: 'brand' }), hits({ - container: '#hits', + container: '#hits2', templates: { - item: (hit, { html, components }) => html` -
-

${components.Highlight({ hit, attribute: 'name' })}

-

${components.Highlight({ hit, attribute: 'description' })}

-
- `, + item: itemComponent, }, }), - configure({ - hitsPerPage: 8, - }), - panel({ - templates: { header: 'brand' }, - })(refinementList)({ - container: '#brand-list', - attribute: 'brand', - }), - pagination({ - container: '#pagination', - }), ]); search.start(); diff --git a/packages/instantsearch.js/src/connectors/hits/connectHits.ts b/packages/instantsearch.js/src/connectors/hits/connectHits.ts index 2e5dc23b25..1885e37f53 100644 --- a/packages/instantsearch.js/src/connectors/hits/connectHits.ts +++ b/packages/instantsearch.js/src/connectors/hits/connectHits.ts @@ -105,6 +105,7 @@ const connectHits: HitsConnector = function connectHits( }, render(renderOptions) { + console.log('rendering hits for ', renderOptions.parent.getIndexName()); const renderState = this.getWidgetRenderState(renderOptions); renderFn( diff --git a/packages/instantsearch.js/src/widgets/index/index.ts b/packages/instantsearch.js/src/widgets/index/index.ts index 13c130aadd..fba782f235 100644 --- a/packages/instantsearch.js/src/widgets/index/index.ts +++ b/packages/instantsearch.js/src/widgets/index/index.ts @@ -17,7 +17,6 @@ import type { IndexUiState, Widget, ScopedResult, - SearchClient, IndexRenderState, } from '../../types'; import type { @@ -36,6 +35,7 @@ const withUsage = createDocumentationMessageGenerator({ export type IndexWidgetParams = { indexName: string; indexId?: string; + separate?: boolean; }; export type IndexInitOptions = { @@ -223,7 +223,7 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { throw new Error(withUsage('The `indexName` option is required.')); } - const { indexName, indexId = indexName } = widgetParams; + const { indexName, indexId = indexName, separate = false } = widgetParams; let localWidgets: Array = []; let localUiState: IndexUiState = {}; @@ -459,10 +459,11 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { // `searchClient`. Only the "main" Helper created at the `InstantSearch` // level is aware of the client. helper = algoliasearchHelper( - {} as SearchClient, + mainHelper.getClient(), parameters.index, parameters ); + const originalSearch = helper.search.bind(helper); // We forward the call to `search` to the "main" instance of the Helper // which is responsible for managing the queries (it's the only one that is @@ -480,7 +481,7 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { return mainHelper; } - return mainHelper.search(); + return separate ? originalSearch() : mainHelper.search(); }; helper.searchWithoutTriggeringOnStateChange = () => { @@ -554,6 +555,12 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { // run the render process in one pass. instantSearchInstance.scheduleRender(); + // Normally we would not request this index + if (separate && helper!.lastResults) { + derivedHelper!.lastResults = helper!.lastResults; + return; + } + // the derived helper is the one which actually searches, but the helper // which is exposed e.g. via instance.helper, doesn't search, and thus // does not have access to lastResults, which it used to in pre-federated @@ -562,6 +569,16 @@ const index = (widgetParams: IndexWidgetParams): IndexWidget => { lastValidSearchParameters = results?._state; }); + if (separate) { + helper.on('result', ({ results, state }) => { + helper!.lastResults = results; + derivedHelper!.lastResults = results; + lastValidSearchParameters = state; + + this.render({ instantSearchInstance }); + }); + } + // We compute the render state before calling `init` in a separate loop // to construct the whole render state object that is then passed to // `init`.