Skip to content

Instantly share code, notes, and snippets.

@timkelty
Last active May 31, 2017 12:24
Show Gist options
  • Select an option

  • Save timkelty/7186587110e649b210d3f948e5420b5f to your computer and use it in GitHub Desktop.

Select an option

Save timkelty/7186587110e649b210d3f948e5420b5f to your computer and use it in GitHub Desktop.
Add facet count to refinement list header
import React from 'react';
import ReactDOM from 'react-dom';
import cx from 'classnames';
import filter from 'lodash/filter';
import RefinementList from 'instantsearch.js/dist-es5-module/src/components/RefinementList/RefinementList.js';
import connectRefinementList from 'instantsearch.js/dist-es5-module/src/connectors/refinement-list/connectRefinementList.js';
import defaultTemplates from 'instantsearch.js/dist-es5-module/src/widgets/refinement-list/defaultTemplates.js';
import getShowMoreConfig from 'instantsearch.js/dist-es5-module/src/lib/show-more/getShowMoreConfig.js';
import {
bemHelper,
prepareTemplateProps,
getContainerNode,
prefixKeys,
} from 'instantsearch.js/dist-es5-module/src/lib/utils.js';
const bem = bemHelper('ais-refinement-list');
const renderer = ({
containerNode,
cssClasses,
transformData,
templates,
renderState,
collapsible,
autoHideContainer,
showMoreConfig,
searchForFacetValues,
}) => ({
refine,
items,
createURL,
searchForItems,
isFromSearch,
instantSearchInstance,
canRefine,
toggleShowMore,
isShowingMore,
hasExhaustiveItems,
canToggleShowMore,
}, isFirstRendering) => {
if (isFirstRendering) {
renderState.templateProps = prepareTemplateProps({
transformData,
defaultTemplates,
templatesConfig: instantSearchInstance.templatesConfig,
templates,
});
return;
}
// Pass count of currently selected items to the header template
const headerFooterData = {
header: {
facetsCount: items.length,
refinedFacetsCount: filter(items, {isRefined: true}).length,
},
};
ReactDOM.render(
<RefinementList
collapsible={collapsible}
createURL={createURL}
cssClasses={cssClasses}
facetValues={items}
headerFooterData={headerFooterData}
shouldAutoHideContainer={autoHideContainer && canRefine === false}
templateProps={renderState.templateProps}
toggleRefinement={refine}
searchFacetValues={searchForFacetValues ? searchForItems : undefined}
searchPlaceholder={searchForFacetValues.placeholder || 'Search for other...'}
isFromSearch={isFromSearch}
showMore={showMoreConfig !== null}
toggleShowMore={toggleShowMore}
isShowingMore={isShowingMore}
hasExhaustiveItems={hasExhaustiveItems}
canToggleShowMore={canToggleShowMore}
/>,
containerNode
);
};
const usage = `Usage:
refinementList({
container,
attributeName,
[ operator='or' ],
[ sortBy=['isRefined', 'count:desc', 'name:asc'] ],
[ limit=10 ],
[ cssClasses.{root, header, body, footer, list, item, active, label, checkbox, count}],
[ templates.{header,item,footer} ],
[ transformData.{item} ],
[ autoHideContainer=true ],
[ collapsible=false ],
[ showMore.{templates: {active, inactive}, limit} ],
[ collapsible=false ],
[ searchForFacetValues.{placeholder, templates: {noResults}}],
})`;
export default function refinementList({
container,
attributeName,
operator = 'or',
sortBy = ['isRefined', 'count:desc', 'name:asc'],
limit = 10,
cssClasses: userCssClasses = {},
templates = defaultTemplates,
collapsible = false,
transformData,
autoHideContainer = true,
showMore = false,
searchForFacetValues = false,
} = {}) {
if (!container) {
throw new Error(usage);
}
const showMoreConfig = getShowMoreConfig(showMore);
if (showMoreConfig && showMoreConfig.limit < limit) {
throw new Error('showMore.limit configuration should be > than the limit in the main configuration'); // eslint-disable-line
}
const showMoreLimit = showMoreConfig && showMoreConfig.limit || limit;
const containerNode = getContainerNode(container);
const showMoreTemplates = showMoreConfig ? prefixKeys('show-more-', showMoreConfig.templates) : {};
const searchForValuesTemplates = searchForFacetValues ? searchForFacetValues.templates : {};
const allTemplates = {...templates, ...showMoreTemplates, ...searchForValuesTemplates};
const cssClasses = {
root: cx(bem(null), userCssClasses.root),
header: cx(bem('header'), userCssClasses.header),
body: cx(bem('body'), userCssClasses.body),
footer: cx(bem('footer'), userCssClasses.footer),
list: cx(bem('list'), userCssClasses.list),
item: cx(bem('item'), userCssClasses.item),
active: cx(bem('item', 'active'), userCssClasses.active),
label: cx(bem('label'), userCssClasses.label),
checkbox: cx(bem('checkbox'), userCssClasses.checkbox),
count: cx(bem('count'), userCssClasses.count),
};
const specializedRenderer = renderer({
containerNode,
cssClasses,
transformData,
templates: allTemplates,
renderState: {},
collapsible,
autoHideContainer,
showMoreConfig,
searchForFacetValues,
});
try {
const makeWidget = connectRefinementList(specializedRenderer);
return makeWidget({
attributeName,
operator,
limit,
showMoreLimit,
sortBy,
});
} catch (e) {
throw new Error(e);
}
}
const search = instantsearch({
appId: 'H3U05083AD',
apiKey: 'fe0fa59fe90d5b76bd19729b71399058',
indexName: 'products',
searchParameters: {
disjunctiveFacetsRefinements: {
'productType.name': ['Kayak'],
}
},
searchFunction: (helper) => {
console.log(helper.state);
helper.search();
}
});
search.addWidget(instantsearch.widgets.refinementList({
container: '#rf1',
attributeName: 'manufacturer.title',
templates: {
header: function(data) {
let hdg = `<h5 class="ais-refinement-list--title">${title}</h5>`;
let facetsCount = data.refinedFacetsCount ? `${data.refinedFacetsCount}/${data.facetsCount}` : data.facetsCount;
facetsCount = facetsCount ? `<span class="ais-refinement-list--facetsCount">${facetsCount}</span>` : '';
return `${hdg}${facetsCount}`;
},
}));
search.start();
@timkelty

Copy link
Copy Markdown
Author

refinement-list.jsx is copied straight from
The only change is passing the facetsCount to the header/footer templates: https://gist.github.com/timkelty/7186587110e649b210d3f948e5420b5f#file-refinement-list-jsx-L56

@timkelty

Copy link
Copy Markdown
Author

refinement-list.jsx is copied straight from
The only change is passing the facetsCount to the header/footer templates: https://gist.github.com/timkelty/7186587110e649b210d3f948e5420b5f#file-refinement-list-jsx-L56

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment