Use an external component action inside a search

The following React example uses an external component action inside a search. This example shows how to use the setModalOperations property to add buttons and associated behavior to the modal footer and perform validation. The setModalOperations property is a function with an array of modal operations.

Note

The setModalOperations property is an extra property that is only available on external components within the external component action.

A modal operation has the following interface.

RequestResponse
interface ModalOperationConfig {
    name: string;
    id: string;
    label: string;
    displayType?: DisplayType;
    className?: string;
    onValidate?: () => boolean | Promise<boolean>;
    onClick?: (event?: unknown) => void | Promise<void>;
    onMouseOver?: (event?: unknown) => void | Promise<void>;
    onContextMenu?: (event?: unknown) => void | Promise<void>;
}

The options for the displayType are: link, default, primary, and secondary.

RequestResponse
import ReactDOM from "react-dom";
import React from "react";
const OptionsContext = React.createContext<any>(null);
type ModalOperationConfig = {
  name: string;
  id: string;
  label: string;
  displayType?: "link" | "default" | "primary" | "secondary" | "none";
  className?: string;
  onValidate?: () => boolean | Promise<boolean>;
  onClick?: (event?: unknown) => void | Promise<void>;
  onMouseOver?: (event?: unknown) => void | Promise<void>;
  onContextMenu?: (event?: unknown) => void | Promise<void>;
};
export default function createExternalRoot(container: HTMLElement) {
  return {
    render(context: any) {
      const {
        api: { notifier },
        options: { setModalOperations, ...options },
      } = context;

      const okButtonConfig: ModalOperationConfig = {
        name: "ok",
        id: "ok",
        label: "Ok",
        displayType: "primary",
        onValidate: () => {
          console.log("validating async...");
          return new Promise((resolve) =>
            setTimeout(() => {
              const isValid = Math.random() > 0.5;
              if (!isValid) {
                notifier.notifyError("Invalid!");
              }
              resolve(isValid);
            }, 500)
          );
        },
        onClick: () => {
          notifier.notifySuccess("Success!");
        },
        onMouseOver: () => {
          console.log("mouseover");
        },
      };

      const cancelButtonConfig: ModalOperationConfig = {
        name: "cancel",
        id: "cancel",
        label: "Cancel",
        onClick: () => {
          notifier.notifyInfo("Canceled");
        },
      };

      setModalOperations([okButtonConfig, cancelButtonConfig]);

      ReactDOM.render(
        <OptionsContext.Provider value={options}>
          <OptionsContext.Consumer>
            {(options) => {
              return (
                <>
                  <div>
                    Showing a modal for entity with id {options.entityId}.
                  </div>
                  <div>Showing a rendition of the entity</div>
                  <img
                    src={context?.entity?.renditions?.preview?.[0]}
                    style={{ maxWidth: "100%" }}
                  />
                </>
              );
            }}
          </OptionsContext.Consumer>
        </OptionsContext.Provider>,
        container
      );
    },
    unmount() {
      ReactDOM.unmountComponentAtNode(container);
    },
  };
}

Do you have some feedback for us?

If you have suggestions for improving this article,