Skip to content

Search Kit Displays

SearchKit Displays are responsible for rendering the results of a SavedSearch query. Each Display has a "type". Most types (Table, List, Grid) are intended to render as part of a webpage (see Embedding Displays), but a few types have specialized output such as an Autocomplete display which populates a form dropdown-select, or an Entity display which writes to a SQL table.

Embedding Displays

Search displays can be embedded in any AngularJS content with their component tag, which requires the name of the SavedSearch, the name of the Display, the name of the entity and the configuration settings, e.g.

<crm-search-display-list search="'MySavedSearch'" display="'MyListDisplay'" api-entity="Contact" settings="{style: 'ul', limit: 50, pager: true, columns: [{key: 'id', dataType: 'Integer', type: 'field'}, {key: 'display_name', dataType: 'String', type: 'field'}]}">
</crm-search-display-list>

That's a lot of data to insert into the markup, and it would get out-of-sync with any updates made to the SavedSearch or SearchDisplay in the database. So Search Kit implements a markup preprocessor to insert the configuration data at runtime. All it needs is the search-name and display-name and it will add the rest:

<crm-search-display-list search-name="MySavedSearch" display-name="MyListDisplay"></crm-search-display-list>

Note: The preprocessor only works on Afforms.

Creating a New Display Type

An extension can add new display types in addition to the ones included with Search Kit (Table, List, etc).

  1. Add the name of the new display type to the search_display_type option list. hook_civicrm_managed() is recommended.
  2. Create an AngularJS module.
  3. In the module's .ang.php file, set 'basePages' => ['civicrm/search', 'civicrm/admin/search'] and 'exports' => ['name-of-your-search-display'].
  4. Add an admin component (ex: searchAdminDisplayList.component.js)
  5. Add a display component (ex: crmSearchDisplayList.component.js)

Embedding an afform in a Smarty Page using Regions

An extension can embed an afform in a CiviCRM Smarty Page using the regions specified in the template. By default, a page would have 3 specified regions: page-header, page-body, page-footer. Additional regions can be added to the page using the {crmRegion} tag. The following steps would help in embedding an afform in any of the Smarty Page assigned regions:

  1. Identify the region on the page by which the afform would be attached. If the template doesn't have custom regions set, you can either set one or use the default page-body region. Using the default page-body would attach the afform to the bottom of the page right above the footer.
  2. Paste the following code in the pageRun Hook of the afform entity's extension:
        if (get_class($page) === '{DISPLAY_PAGE_CLASS_NAME}') {
          Civi::service('angularjs.loader')->addModules('{afformModuleName}');
          CRM_Core_Region::instance(`{PAGE_REGION}`)->add([
            'markup' => '<crm-angular-js modules="{afformModuleName}"><form id="bootstrap-theme"><{afform-directive-name}></afform-directive-name></form></crm-angular-js>',
          ]);
        }
    
  3. {DISPLAY_PAGE_CLASS_NAME} is the class name for the Smarty page. This can be gotten from the Route entity using the url path to the page. For example, to get the class for the page with path /lorem/ipsum/text use: cv api4 Route.get '{"where":[["path","=","lorem/ipsum/text"]],"limit":25,"select":["page_callback"]}'
  4. {afformModuleName} and {afform-directive-name} can be gotten using the Afform entity and the name of the afform (which can be gotten from the formbuilder/search forms list). For example, to get the moduleName and directiveName for an afform named afTestAfform, use: cv api4 Afform.get '{"where":[["name","=","afTestAfform"]],"limit":25,"select":["module_name","directive_name"]}'
  5. {PAGE_REGION} is the specific region where you want the afform to be embedded. For pages with no specified region, using page-body should place the afform below the last component on the template before the footer.

  6. Refreshing the page should display the afform in the position of the page region.

Passing data to an afform embedded in a Smarty Page to filter a Search table

Here are the steps to pass data into an embedded afform for filtering by an id: 1. Add the data to the options attribute of the afform. In the example below, the embedded afform (afSearchTest) is passed an id with value 100 through the options attribute:

    if (get_class($page) === 'CRM_Contribute_Page_DashBoard') {
      Civi::service('angularjs.loader')->addModules('afSearchTest');
      CRM_Core_Region::instance(`{PAGE_REGION}`)->add([
        'markup' => '<crm-angular-js modules="afSearchTest"><form id="bootstrap-theme"><afsearch-test options="{id: 100}"></afsearch-test></form></crm-angular-js>',
      ]);
    }
2. In the generated afform html file in the ang directory, specify this id gotten from the options attribute as the filter-by value in the search display table:

  <crm-search-display-table search-name="MySavedSearch" display-name="MyListDisplay" filters="{id: options.id}"></crm-search-display-table>