Implement folding
Implement folding
This is for:
DeveloperCoveo Atomic 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
component.
Prerequisites
Before pushing any data to the Coveo index, make sure that the data you’re working with has established parent-child relationships. Some data may 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 via the Coveo Administration Console, which means you need to implement such data processing in your own infrastructure. |
Once your data has established parent-child relationships, you need to push the data to your Coveo organization and then create the proper folding fields for the target items.
Main features
The atomic-folded-result-list
component is similar to the atomic-result-list
component, but provides extra functionality.
This component requires no extra configuration apart from specifying the three folding fields:
The atomic-folded-result-list
requires one or more atomic-result-template
components to display the results.
This result template can include an atomic-result-children
component with nested atomic-result-children-template
components to render the child results.
The atomic-result-children
component also offers two slots named before-children
and after-children
.
They’re available via the attributes slot="before-children"
and slot="after-children"
.
These slots let you insert a list of children only when children are available for that specific result.
The slots let you insert a component inside atomic-result-children
but outside any templates.
Child elements
The following sample shows the basic structure to fold results with one child.
<atomic-folded-result-list>
<atomic-result-template>
<!-- RESULT template defined here -->
<atomic-result-children>
<atomic-result-children-template>
<!-- CHILD template defined here -->
</atomic-result-children-template>
</atomic-result-children>
</atomic-result-template>
</atomic-folded-result-list>
The |
Grandchild elements
To render grandchildren, you need to add an extra layer, as in the following example:
<atomic-folded-result-list>
<atomic-result-template>
<!-- RESULT template defined here -->
<atomic-result-children>
<atomic-result-children-template>
<!-- CHILD template defined here -->
<atomic-result-children>
<atomic-result-children-template inherit-templates="true">
<!-- GRANDCHILD template defined here -->
</atomic-result-children-template>
</atomic-result-children>
</atomic-result-children-template>
</atomic-result-children>
</atomic-result-template>
</atomic-folded-result-list>
If you want the grandchildren to be the same as the children, you can set inherit-templates attribute to true on the grandchild level and omit the templates.
With that option, you can either leave the atomic-result-children-template empty or still specify its own templates which will take priority over children (or inherited) templates. |
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:-
Template 3 (defined at the grandchild level)
-
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.
Comprehensive example
The following example uses all the features mentioned in the previous sections.
Note that templates are only available within the scope in which they’re defined.
For example, an atomic-result-children-template
child defined inside an atomic-result-template
will only be available for results that match both templates.
An atomic-result-children-template
that’s a child of another atomic-result-children-template
will similarly only be available for results that match both these templates.
If you need to reuse templates, you can define them outside of the scope of the results and refer to them by ID anywhere you want to place them.
<atomic-folded-result-list>
<atomic-result-template must-match-sourcetype="YouTube">
<template>
<img src="https://www.youtube.com/s/desktop/406de18b/img/favicon_32x32.png" class="thumbnail" />
<atomic-result-link></atomic-result-link>
</template>
</atomic-result-template>
<atomic-result-template must-match-sourcetype="Twitter">
<template>
<img src="https://cdn.cms-twdigitalassets.com/content/dam/developer-twitter/images/Twitter_logo_blue_32.png" class="thumbnail" />
<atomic-result-link></atomic-result-link>
<atomic-result-fields-list>
<atomic-result-text field="excerpt"></atomic-result-text>
<span class="field-label"><atomic-text value="author"></atomic-text>:</span>
<atomic-result-text field="author"></atomic-result-text>
</atomic-result-fields-list>
<div class="thread">
<atomic-result-children>
<atomic-result-children-template>
<template>
<span class="field-label"><atomic-text value="author"></atomic-text>:</span>
<atomic-result-text field="author"></atomic-result-text>
<atomic-result-text field="excerpt"></atomic-result-text>
<div class="thread">
<atomic-result-children inherit-templates>
</atomic-result-children>
</div>
</template>
</atomic-result-children-template>
</atomic-result-children>
</div>
</template>
</atomic-result-template>
<atomic-result-template must-match-sourcetype="Slack">
<template>
<img src="https://cdn.bfldr.com/5H442O3W/at/pl546j-7le8zk-6gwiyo/Slack_Mark.svg?auto=webp&format=svg&width=32&height=32" class="thumbnail" />
<atomic-result-link></atomic-result-link>
<atomic-result-fields-list>
<atomic-result-text field="excerpt"></atomic-result-text>
<span class="field-label"><atomic-text value="author"></atomic-text>:</span>
<atomic-result-text field="author"></atomic-result-text>
</atomic-result-fields-list>
<div class="thread">
<atomic-result-children>
<p slot="before-children">Available files:</p>
<atomic-result-children-template must-match-type="uploadedFile">
<template>
<atomic-result-icon class="icon"></atomic-result-icon>
</template>
</atomic-result-children-template>
</atomic-result-children>
</div>
</template>
</atomic-result-template>
</atomic-folded-result-list>
YouTube results will ignore any children as no atomic-result-children components are present here. |
|
Twitter results will show children and grandchildren. | |
Grandchild results will inherit the templates from their parent (child results). | |
Slack results will only show children that are uploaded files and ignore grandchildren. | |
The p element will only be rendered when a Slack result has children. |
Folding in rendering functions
The atomic-folded-result-list
component allows you to set the templates by passing it to a renderingFunction
that will return a FoldedResult
, which you can then use to render its children or grandchildren as well.
The following is an example of such usage in Atomic React:
import React, {FunctionComponent} from 'react';
import {
AtomicFormatCurrency,
AtomicResultBadge,
AtomicResultFieldsList,
AtomicResultImage,
AtomicResultLink,
AtomicResultMultiValueText,
AtomicResultNumber,
AtomicResultPrintableUri,
AtomicResultRating,
AtomicResultSectionBadges,
AtomicResultSectionBottomMetadata,
AtomicResultSectionEmphasized,
AtomicResultSectionExcerpt,
AtomicResultSectionTitle,
AtomicResultSectionTitleMetadata,
AtomicResultSectionVisual,
AtomicResultText,
AtomicText,
FoldedResult,
AtomicResultSectionChildren,
AtomicFoldedResultList,
AtomicResultChildren,
AtomicResultChildrenTemplate,
} from '@coveo/atomic-react';
import {AtomicApp} from './AtomicApp';
export const Folded: FunctionComponent = () => {
return (
<AtomicApp
accessToken="xx564559b1-0045-48e1-953c-3addd1ee4457"
organizationId="searchuisamples"
>
<AtomicFoldedResultList
fieldsToInclude={["ec_price","ec_rating","ec_images","ec_brand","cat_platform","cat_condition","cat_categories","cat_review_count","cat_color"]}
imageSize="large"
template={MyTemplate}
/>
</AtomicApp>
);
};
function MyTemplate(result: FoldedResult) {
return (
<>
<AtomicResultSectionBadges>
<AtomicResultBadge field="ec_brand" />
</AtomicResultSectionBadges>
<AtomicResultSectionVisual>
<AtomicResultImage field="ec_images" />
</AtomicResultSectionVisual>
<AtomicResultSectionTitle>
<AtomicResultLink />
</AtomicResultSectionTitle>
<AtomicResultSectionTitleMetadata>
<AtomicResultRating field="ec_rating" />
<AtomicResultPrintableUri maxNumberOfParts={3} />
</AtomicResultSectionTitleMetadata>
<AtomicResultSectionEmphasized>
<AtomicResultNumber field="ec_price">
<AtomicFormatCurrency currency="USD" />
</AtomicResultNumber>
</AtomicResultSectionEmphasized>
<AtomicResultSectionExcerpt>
<AtomicResultText field="ec_shortdesc" />
</AtomicResultSectionExcerpt>
<AtomicResultSectionChildren>
<AtomicResultChildren>
<AtomicResultChildrenTemplate>
<template>
<AtomicResultLink />
</template>
</AtomicResultChildrenTemplate>
</AtomicResultChildren>
</AtomicResultSectionChildren>
<AtomicResultSectionBottomMetadata>
<AtomicResultFieldsList>
{result.result.raw.cat_platform && (
<>
<span className="field-label">
<AtomicText value="Platform" />
</span>
<AtomicResultText field="cat_platform" />
</>
)}
{result.result.raw.cat_condition && (
<>
<span className="field-label">
<AtomicText value="Condition" />
</span>
<AtomicResultText field="cat_condition" />
</>
)}
{result.result.raw.cat_categories && (
<>
<span className="field-label">
<AtomicText value="Tags" />
</span>
<AtomicResultMultiValueText field="cat_categories" />
</>
)}
</AtomicResultFieldsList>
</AtomicResultSectionBottomMetadata>
</>
);
}
This is where you define children. |
Although you can still use the Atomic components to render children, FoldedResult
offers you the children
prop where you have access to the children results in the main function too.