---
title: Implement folding
slug: latest-folding
canonical_url: https://docs.coveo.com/en/atomic/latest/usage/displaying-results/folding/
collection: atomic
source_format: adoc
---
# Implement folding

[Coveo Atomic](https://docs.coveo.com/en/lcdf0264.md) lets you display search results that have a parent-child relationship with any level of nesting.
This article explains how to build hierarchical result lists using the [`atomic-folded-result-list`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-folded-result-list/) component.

## Prerequisites

Before [indexing](https://docs.coveo.com/en/204.md) data, make sure that the data you're working with has established parent-child relationships.
Some data might already have these relationships when you collected it.
If not, you'll need to build a relationship graph yourself.

> **Note**
>
> You can't create parent-child relationships directly in the [Coveo Administration Console](https://docs.coveo.com/en/183.md).
> The target metadata exist in the items you want to index, this could require you to implement the necessary data processing in your own infrastructure.

Once your data has established parent-child relationships codified in the target metadata, create the proper [folding fields](https://docs.coveo.com/en/1884.md) and mappings for the target items, and index your content.
The fields you specify for `collection-field`, `parent-field`, and  `child-field` must exist on the target items.

## Main features

The [`atomic-folded-result-list`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-folded-result-list) component is similar to the [`atomic-result-list`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-result-list/) component, but provides extra functionality.
This component requires no extra configuration apart from specifying the three folding fields that were configured for these items:

* `collection-field`

* `parent-field`

* `child-field`

It's recommended to provide `atomic-folded-result-list` one or more [`atomic-result-template`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-result-template/) components to display the results.
Each result template can include an [`atomic-result-children`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-result-children/) component with nested [`atomic-result-children-template`](https://docs.coveo.com/en/atomic/latest/reference/components/atomic-result-children-template/) components to render the child results.

## Basic structure

The following example shows an `atomic-folded-result-list` with parent and child result templates, including grandchild rendering through `inherit-templates`:

[%collapsible]

**Details**

#### ```html

<atomic-folded-result-list <1>

  collection-field="foldingcollection" <2>

  parent-field="foldingparent"

  child-field="foldingchild"

  number-of-folded-results="2"

>

  <atomic-result-template must-match-sourcetype="YouTube">

    <template> <3>

      <atomic-result-section-title>

        <atomic-result-link></atomic-result-link>

      </atomic-result-section-title>

      <atomic-result-section-excerpt>

        <atomic-result-text field="excerpt"></atomic-result-text>

      </atomic-result-section-excerpt>

    </template>

  </atomic-result-template>

  <atomic-result-template must-match-sourcetype="Slack">

    <template> <4>

      <atomic-result-section-title>

        <atomic-result-link></atomic-result-link>

      </atomic-result-section-title>

      <atomic-result-section-excerpt>

        <atomic-result-text field="excerpt"></atomic-result-text>

      </atomic-result-section-excerpt>

      <atomic-result-section-bottom-metadata>

        <atomic-result-fields-list>

          <atomic-result-text field="author"></atomic-result-text>

        </atomic-result-fields-list>

      </atomic-result-section-bottom-metadata>

      <atomic-result-section-children>

        <atomic-result-children image-size="icon">

          
Attached files:
 <5>

          <atomic-result-children-template must-match-filetype="pdf">

            <template> <6>

              <atomic-result-section-title>

                <atomic-result-link></atomic-result-link>

              </atomic-result-section-title>

            </template>

          </atomic-result-children-template>

        </atomic-result-children>

      </atomic-result-section-children>

    </template>

  </atomic-result-template>

  <atomic-result-template>

    <template> <7>

      <atomic-result-section-title>

        <atomic-result-link></atomic-result-link>

      </atomic-result-section-title>

      <atomic-result-section-excerpt>

        <atomic-result-text field="excerpt"></atomic-result-text>

      </atomic-result-section-excerpt>

      <atomic-result-section-children> <8>

        <atomic-result-children image-size="icon"> <9>

          <atomic-result-children-template> <10>

            <template>

              <atomic-result-section-title>

                <atomic-result-link></atomic-result-link>

              </atomic-result-section-title>

              <atomic-result-section-excerpt>

                <atomic-result-text field="excerpt"></atomic-result-text>

              </atomic-result-section-excerpt>

              <atomic-result-section-children>

                <atomic-result-children inherit-templates> <11>

                </atomic-result-children>

              </atomic-result-section-children>

            </template>

          </atomic-result-children-template>

        </atomic-result-children>

      </atomic-result-section-children>

    </template>

  </atomic-result-template>

</atomic-folded-result-list>

```



<1> Use `atomic-folded-result-list` instead of `atomic-result-list` to enable folding.

<2> Specify your [folding fields]({site-baseurl}/1466/). These map to `filterField`, `parentField`, and `childField` in the Search API.

<3> This template only applies to YouTube results. Because it has no `atomic-result-children`, children are ignored for YouTube results.

<4> This template applies to Slack results. It includes children rendering.

<5> The `before-children` slot renders content only when children exist.

<6> Use `must-match-filetype` to conditionally render only PDF attachments as children.

<7> A default result template applies to any result that doesn't match the templates above.

<8> The `atomic-result-section-children` section is where child results appear.

<9> `atomic-result-children` handles the display of child results and the "Show more"/"Show less" toggle.

<10> Define a template for child results.

<11> Nest another `atomic-result-children` for grandchild rendering. Set `inherit-templates` to reuse the child template.

#### === Grandchild elements


To render grandchildren, nest an additional `atomic-result-children` inside a child template.
Alternatively, if the `inherit-templates` property is set on a `atomic-result-children` component, the grandchild will use the template from its immediate element parent for rendering elements.

```html

<atomic-result-children-template>

  <template>

    <atomic-result-section-title>

      <atomic-result-link></atomic-result-link>

    </atomic-result-section-title>

    <atomic-result-section-excerpt>

      <atomic-result-text field="excerpt"></atomic-result-text>

    </atomic-result-section-excerpt>

    <atomic-result-section-children>

      <atomic-result-children inherit-templates> <1>

      </atomic-result-children>

    </atomic-result-section-children>

  </template>

</atomic-result-children-template>

```

<1> Nest another `atomic-result-children` for grandchild rendering. Set `inherit-templates` to reuse the child template.
The grandchild rendering depends on templates and the value of the `inherit-templates` option.
For example:

* The child defines template 1 and template 2; the grandchild defines template 3 and has `inherit-templates="true"`.
The grandchild will use the templates in the following order:

   1. Template 3 (defined at the grandchild level)

   1. Template 1 and template 2 (both defined at the child level, in this order)

* The child defines template 1 and template 2; the grandchild defines template 3 and `inherit-templates` is set to `"false"` or not specified.
The grandchild will only use template 3 and ignore the other two.

## Conditional templates

You can define multiple `atomic-result-template` elements that apply to different source types.
Templates are only available within the scope in which they're defined.

The following example uses `must-match-sourcetype` to render YouTube and Slack results differently, with Slack results showing children filtered by file type:

```html

<atomic-result-template must-match-sourcetype="YouTube">

  <template> <1>

    <atomic-result-section-title>

      <atomic-result-link></atomic-result-link>

    </atomic-result-section-title>

    <atomic-result-section-excerpt>

      <atomic-result-text field="excerpt"></atomic-result-text>

    </atomic-result-section-excerpt>

  </template>

</atomic-result-template>

<atomic-result-template must-match-sourcetype="Slack">

  <template> <2>

    <atomic-result-section-title>

      <atomic-result-link></atomic-result-link>

    </atomic-result-section-title>

    <atomic-result-section-excerpt>

      <atomic-result-text field="excerpt"></atomic-result-text>

    </atomic-result-section-excerpt>

    <atomic-result-section-bottom-metadata>

      <atomic-result-fields-list>

        <atomic-result-text field="author"></atomic-result-text>

      </atomic-result-fields-list>

    </atomic-result-section-bottom-metadata>

    <atomic-result-section-children>

      <atomic-result-children image-size="icon">

        <p slot="before-children">Attached files:</p> <3>

        <atomic-result-children-template must-match-filetype="pdf">

          <template> <4>

            <atomic-result-section-title>

              <atomic-result-link></atomic-result-link>

            </atomic-result-section-title>

          </template>

        </atomic-result-children-template>

      </atomic-result-children>

    </atomic-result-section-children>

  </template>

</atomic-result-template>

```

<1> This template only applies to YouTube results. Because it has no `atomic-result-children`, children are ignored for YouTube results.

<2> This template applies to Slack results. It includes children rendering.

<3> The `before-children` slot renders content only when children exist.

<4> Use `must-match-filetype` to conditionally render only PDF attachments as children.
## Complete example

The following is the complete, runnable page that combines all the folding concepts introduced earlier:

[%collapsible]

**Details**

#### ```html

<!doctype html>

<html lang="en">

  <head>

    <script type="module" src="https://static.cloud.coveo.com/atomic/v3.61.5/atomic.esm.js"></script> <1>

    <link rel="stylesheet" href="https://static.cloud.coveo.com/atomic/v3.61.5/themes/coveo.css"/>

    <script type="module" src="./folding-init.js"></script> <2>

  </head>

  <body>

    <atomic-search-interface id="search-interface">

      <atomic-search-box></atomic-search-box>

      <!-- // tag::basic-structure[] -->

      <atomic-folded-result-list <3>

        collection-field="foldingcollection" <4>

        parent-field="foldingparent"

        child-field="foldingchild"

        number-of-folded-results="2"

      >

        <!-- // tag::comprehensive[] -->

        <atomic-result-template must-match-sourcetype="YouTube">

          <template> <5>

            <atomic-result-section-title>

              <atomic-result-link></atomic-result-link>

            </atomic-result-section-title>

            <atomic-result-section-excerpt>

              <atomic-result-text field="excerpt"></atomic-result-text>

            </atomic-result-section-excerpt>

          </template>

        </atomic-result-template>

        <atomic-result-template must-match-sourcetype="Slack">

          <template> <6>

            <atomic-result-section-title>

              <atomic-result-link></atomic-result-link>

            </atomic-result-section-title>

            <atomic-result-section-excerpt>

              <atomic-result-text field="excerpt"></atomic-result-text>

            </atomic-result-section-excerpt>

            <atomic-result-section-bottom-metadata>

              <atomic-result-fields-list>

                <atomic-result-text field="author"></atomic-result-text>

              </atomic-result-fields-list>

            </atomic-result-section-bottom-metadata>

            <atomic-result-section-children>

              <atomic-result-children image-size="icon">

                
Attached files:
 <7>

                <atomic-result-children-template must-match-filetype="pdf">

                  <template> <8>

                    <atomic-result-section-title>

                      <atomic-result-link></atomic-result-link>

                    </atomic-result-section-title>

                  </template>

                </atomic-result-children-template>

              </atomic-result-children>

            </atomic-result-section-children>

          </template>

        </atomic-result-template>

        <!-- // end::comprehensive[] -->

        <atomic-result-template>

          <template> <9>

            <atomic-result-section-title>

              <atomic-result-link></atomic-result-link>

            </atomic-result-section-title>

            <atomic-result-section-excerpt>

              <atomic-result-text field="excerpt"></atomic-result-text>

            </atomic-result-section-excerpt>

            <atomic-result-section-children> <10>

              <atomic-result-children image-size="icon"> <11>

                <!-- // tag::grandchild[] --> <12>

                <atomic-result-children-template>

                  <template>

                    <atomic-result-section-title>

                      <atomic-result-link></atomic-result-link>

                    </atomic-result-section-title>

                    <atomic-result-section-excerpt>

                      <atomic-result-text field="excerpt"></atomic-result-text>

                    </atomic-result-section-excerpt>

                    <atomic-result-section-children>

                      <atomic-result-children inherit-templates> <13>

                      </atomic-result-children>

                    </atomic-result-section-children>

                  </template>

                </atomic-result-children-template>

                <!-- // end::grandchild[] -->

              </atomic-result-children>

            </atomic-result-section-children>

          </template>

        </atomic-result-template>

      </atomic-folded-result-list>

      <!-- // end::basic-structure[] -->

    </atomic-search-interface>

  </body>

</html>

```



<1> Load the Atomic library and default theme from the CDN.

<2> Load the initialization script.

<3> Use `atomic-folded-result-list` instead of `atomic-result-list` to enable folding.

<4> Specify your [folding fields]({site-baseurl}/1466/). These map to `filterField`, `parentField`, and `childField` in the Search API.

<5> This template only applies to YouTube results. Because it has no `atomic-result-children`, children are ignored for YouTube results.

<6> This template applies to Slack results. It includes children rendering.

<7> The `before-children` slot renders content only when children exist.

<8> Use `must-match-filetype` to conditionally render only PDF attachments as children.

<9> A default result template applies to any result that doesn't match the templates above.

<10> The `atomic-result-section-children` section is where child results appear.

<11> `atomic-result-children` handles the display of child results and the "Show more"/"Show less" toggle.

<12> Define a template for child results.

<13> Nest another `atomic-result-children` for grandchild rendering. Set `inherit-templates` to reuse the child template.

#### The initialization script sets up the search engine and triggers the first search:


```js

// folding-init.js

import {getSampleSearchEngineConfiguration} from 'https://static.cloud.coveo.com/headless/v3.57.1/headless.esm.js';



(async () => {

  await customElements.whenDefined('atomic-search-interface'); <1>



  const searchInterface = document.querySelector(

    'atomic-search-interface#search-interface' <2>

  );



  if (!searchInterface) return;



  await searchInterface.initialize({

    ...getSampleSearchEngineConfiguration(), <3>

  });



  searchInterface.executeFirstSearch(); <4>

})();

```

<1> Wait for the `atomic-search-interface` component to be registered.

<2> Target the search interface element by its ID.

<3> Replace with your own [`SearchEngineConfiguration`]({typedocurl}/interfaces/Search.SearchEngineConfiguration.html).

<4> Execute the initial search to populate the folded result list.
For more details on defining result templates, see [Displaying results](https://docs.coveo.com/en/atomic/latest/usage/displaying-results#defining-a-result-template).

## Folding in rendering functions

Instead of using HTML templates to define how folded results render, you can write a custom rendering function.
A rendering function receives a `FoldedResult` object and returns rendered output for the result and its children.

In [Atomic React](https://docs.coveo.com/en/atomic/latest/usage/frameworks/atomic-react-wrapper/), you pass this function through the `template` prop (for example, `<AtomicFoldedResultList template=\{MyTemplate} />`).
In other frameworks, you call the `setRenderFunction()` method on the `atomic-folded-result-list` DOM element.

> **Warning**
>
> Atomic React doesn't support `atomic-result-children`, `atomic-result-children-template`, or other Atomic template components inside child results.
> You must use a rendering function to render folded child results in React.

The following is a [example](https://github.com/coveo/ui-kit/blob/main/samples/atomic/search-commerce-react/src/pages/FoldedResultListPage.tsx) that uses a rendering function to perform folding in Atomic React:

```tsx

import {

  AtomicFoldedResultList,

  AtomicResultFieldsList,

  AtomicResultLink,

  AtomicResultMultiValueText,

  AtomicResultSectionBottomMetadata,

  AtomicResultSectionChildren,

  AtomicResultSectionExcerpt,

  AtomicResultSectionTitle,

  AtomicResultText,

  AtomicSearchBox,

  AtomicSearchInterface,

} from '@coveo/atomic-react'; <1>

import type {FoldedResult} from '@coveo/headless'; <2>

import {

  buildSearchEngine,

  getSampleSearchEngineConfiguration,

} from '@coveo/headless';

import {type FunctionComponent, useMemo} from 'react';



export const FoldedResultListPage: FunctionComponent = () => {

  const engine = useMemo( <3>

    () =>

      buildSearchEngine({

        configuration: getSampleSearchEngineConfiguration(),

      }),

    []

  );



  return (

    <AtomicSearchInterface engine={engine}>

      <AtomicSearchBox />

      <AtomicFoldedResultList template={MyTemplate} /> <4>

    </AtomicSearchInterface>

  );

};



function MyTemplate(result: FoldedResult) { <5>

  return (

    <>

      <AtomicResultSectionTitle>

        <AtomicResultLink />

      </AtomicResultSectionTitle>

      <AtomicResultSectionExcerpt>

        <AtomicResultText field="excerpt" />

      </AtomicResultSectionExcerpt>

      <AtomicResultSectionChildren> <6>

        {!!result.children.length && (

          <div>

            <strong>Child results:</strong>

            <ul>

              {result.children.map((child, i) => (

                <li key={child.result.uniqueId}>

                  <strong>Child {i + 1}: </strong>

                  <a href={child.result.clickUri}>{child.result.title}</a>

                </li>

              ))}

            </ul>

          </div>

        )}

      </AtomicResultSectionChildren>

      <AtomicResultSectionBottomMetadata>

        <AtomicResultFieldsList>

          {Boolean(result.result.raw.author) && (

            <div className="field">

              <span className="field-label">Author: </span>

              <AtomicResultText field="author" />

            </div>

          )}

          {Boolean(result.result.raw.language) && (

            <div className="field">

              <span className="field-label">Language: </span>

              <AtomicResultMultiValueText field="language" />

            </div>

          )}

        </AtomicResultFieldsList>

      </AtomicResultSectionBottomMetadata>

    </>

  );

}

```

<1> Import the Atomic React components. In React, you use JSX wrappers instead of web component tags.

<2> `FoldedResult` is the type passed to your rendering function. It contains `result` (the current item) and `children` (an array of `FoldedResult`).

<3> Create a search engine instance using the sample configuration from `@coveo/headless`.

<4> Pass a `template` function to `AtomicFoldedResultList`. This function receives a `FoldedResult` and returns JSX.

<5> The template function receives the full `FoldedResult` object, giving you access to `result.children` for rendering child items.

<6> Use `AtomicResultSectionChildren` to define where child results appear. Access `result.children` directly to render them with custom JSX.