Example using the search event

The following React example shows how to use the methods and SEARCH_FINISHED event.

Note

This event is available starting from Content Hub version 4.2.18.

index.tsx

import ReactDOM from "react-dom";
import React from "react";
import AddSearchFilters from "./AddSearchFilters";
import { FieldFilterRequestResource } from "@sitecore/sc-contenthub-webclient-sdk/dist/models/search/field-filter-request-resource";

interface Context {
  config: {
    searchIdentifier: string;
  };
  options: {
    entityId?: number;
  };
  api: {
    search: {
      addFilters: (
        searchIdentifier: string,
        filters: Array<FieldFilterRequestResource>
      ) => void;
      updateQuery: (searchIdentifier: string, query: string) => void;
      updateFullTextFilter: (searchIdentifier: string, text: string) => void;
      clearFullTextFilter: (searchIdentifier: string) => void;
      getEventSearchIdentifier: (searchIdentifier: string) => string;
    };
  };
}

export default function createExternalRoot(container: HTMLElement) {
  return {
    render(context: Context) {
      const {
        addFilters,
        updateQuery,
        clearFullTextFilter,
        updateFullTextFilter,
        getEventSearchIdentifier,
      } = context.api.search;

      ReactDOM.render(
        <AddSearchFilters
          searchIdentifier={context.config.searchIdentifier}
          addFilters={addFilters}
          updateQuery={updateQuery}
          clearFullTextFilter={clearFullTextFilter}
          updateFullTextFilter={updateFullTextFilter}
          getEventSearchIdentifier={getEventSearchIdentifier}
        />,
        container
      );
    },
    unmount() {
      ReactDOM.unmountComponentAtNode(container);
    },
  };
}

AddSearchFilters.tsx

import { Nullable } from "@sitecore/sc-contenthub-webclient-sdk";
import { FieldFilterRequestResource } from "@sitecore/sc-contenthub-webclient-sdk/dist/models/search/field-filter-request-resource";
import { FieldFilterResponseResource } from "@sitecore/sc-contenthub-webclient-sdk/dist/models/search/field-filter-response-resource";
import { FilterOperator } from "@sitecore/sc-contenthub-webclient-sdk/dist/models/search/filter-operator";
import { RequestedFilterType } from "@sitecore/sc-contenthub-webclient-sdk/dist/models/search/requested-filter-type";

import React, { FunctionComponent, useEffect, useState } from "react";

interface SearchInteractionProps {
  /**
   * The identifier of the search component whose filter changes we want to track.
   */
  searchIdentifier: string;

  /**
   * A callback to add filters to the search component.
   */
  addFilters: (
    searchIdentifier: string,
    filters: Array<FieldFilterRequestResource>
  ) => void;

  /**
   * A callback to update the current query (e.g. to remove filters).
   */
  updateQuery: (searchIdentifier: string, query: string) => void;

  /**
   * A callback to update the full text filter.
   */
  updateFullTextFilter: (searchIdentifier: string, text: string) => void;

  /**
   * A callback to clear the full text filter.
   */
  clearFullTextFilter: (searchIdentifier: string) => void;

  /**
   * A function that returns the correct search identifier to check for when listening to the SEARCH_CHANGED event
   */
  getEventSearchIdentifier: (searchIdentifier: string) => string;
}

interface FullTextFilter {
  /**
   * The current full text filter.
   */
  value: string;

  /**
   * The encoded query without the full text filter.
   */
  removeQuery: string;
}

const AddSearchFilters: FunctionComponent<SearchInteractionProps> = ({
  searchIdentifier,
  addFilters,
  updateQuery,
  clearFullTextFilter,
  updateFullTextFilter,
  getEventSearchIdentifier,
}) => {
  const [appliedSearchFilters, setAppliedSearchFilters] = useState<
    Array<FieldFilterResponseResource>
  >([]);

  const [fullTextFilterValue, setFullTextFilterValue] = useState<string>("");

  const addSearchFilter = () => {
    // We setup some filters to add.
    const extraFilters = [
      new FieldFilterRequestResource({
        fieldName: "taxonomy_items.64.*",
        values: [1025],
        nestedValues: [],
        operator: FilterOperator.AnyOf,
        visible: true,
        hidden: true,
        multiSelect: true,
        filterType: RequestedFilterType.InFilter,
      }),
    ];

    // We call the callback function and pass the search identifier and filters to add.
    addFilters(searchIdentifier, extraFilters);
  };

  useEffect(() => {
    // Whe the search has finished we show the updated filters
    const onSearchFinished = (evt: Event): void => {
      const {
        filters,
        searchIdentifier: eventSearchIdentifier, // We rename the property to eventSearchIdentifier.
        fullText,
      } = (
        evt as CustomEvent<{
          searchIdentifier: string;
          fullText: string;
          filters: Array<FieldFilterResponseResource>;
          ids: Array<number>;
        }>
      ).detail;

      // We check if the searchIdentifier on the event is the one we are interested in.
      if (
        eventSearchIdentifier === getEventSearchIdentifier(searchIdentifier)
      ) {
        setAppliedSearchFilters(filters);
        setFullTextFilterValue(fullText);
      }
    };

    window.addEventListener("SEARCH_FINISHED", onSearchFinished);

    return () => {
      window.removeEventListener("SEARCH_FINISHED", onSearchFinished);
    };
  }, []);

  return (
    <>
      <button onClick={addSearchFilter}>Add search filter</button>
      {appliedSearchFilters.map((filter) => (
        <button
          onClick={() => updateQuery(searchIdentifier, filter.removeQuery)}
        >
          Remove {filter.label}
        </button>
      ))}
      {appliedSearchFilters.length > 0 && (
        <>
          <h4>Currently applied filters</h4>
          <pre>{JSON.stringify(appliedSearchFilters, undefined, 4)}</pre>
        </>
      )}

      <>
        <h4>Full text filter</h4>
        <input
          type="text"
          value={fullTextFilterValue}
          onChange={(e) => setFullTextFilterValue(e.target.value)}
        />
        <button
          onClick={() =>
            updateFullTextFilter(searchIdentifier, fullTextFilterValue)
          }
        >
          Update fullText filter
        </button>
        <button onClick={() => clearFullTextFilter(searchIdentifier)}>
          Delete fullText filter
        </button>
      </>
    </>
  );
};

export default AddSearchFilters;