Step 2: Selecting a Facet
Back in the custom facet component, you’ll need to add a function to handle clicks on each facet option. To select a facet option in the search state, add the useSearchActions
hook and write a function (handleFacetClick
in this example) to toggle the option’s selected value from false to true and vice-versa.
// src/components/TileFacet.tsx
import {
// Matcher and NumberRangeValue will be used in step 3
Matcher,
NumberRangeValue,
useSearchActions,
useSearchState,
} from "@yext/search-headless-react";
import classNames from "classnames";
interface TileFacetProps {
fieldId: string;
displayName?: string;
}
const TileFacet = ({ fieldId, displayName }: TileFacetProps) => {
const searchActions = useSearchActions();
const facet = useSearchState((state) =>
state.filters.facets?.find((f) => f.fieldId === fieldId)
);
const handleFacetClick = (
value: string | number | boolean | NumberRangeValue,
selected: boolean,
matcher = Matcher.Equals
) => {
searchActions.setFacetOption(fieldId, { matcher, value }, selected);
searchActions.executeVerticalQuery();
};
// component returns null if the facet isn't found in the search state or has no options for a partiaular set of results
return facet && facet.options.length > 0 ? (
<div className="mb-4">
<span className="font-bold ">{displayName ?? facet.displayName}</span>
<div key={facet.fieldId} className="w-72 mt-6 flex flex-wrap">
{facet.options.map((o, i) => (
<div
key={`${fieldId}_${i}`}
className={classNames(
"mr-3 mb-3 border border-toast-orange md:hover:bg-[#FFB563]",
// styling to change the background color of the tile based on if it's selected or not
{
"bg-[#FFB563]": o.selected,
"bg-[#FFEEDB]": !o.selected,
}
)}
// handleFacetClick will trigger on click to reverse the selected state of the facet option
onClick={() => handleFacetClick(o.value, !o.selected)}
>
<div className="px-3 text-sm inline-block">
{/* Each facet option contains a display name and count */}
<span className="mr-0.5">{o.displayName}</span>
<span className="text-xs">{`(${o.count})`}</span>
</div>
</div>
))}
</div>
</div>
) : null;
};
export default TileFacet;
<% elem.innerText %>