Integrate a Custom Component in Sitecore Using the Coveo Hive Framework

In this article
Warning
Legacy feature

This article pertains to the Coveo Hive framework which is now in maintenance mode.

Choose one of Coveo’s more modern, lightweight, and responsive libraries for any future search interface development. See the search interface Implementation guide for more details.

This page covers how to integrate a custom Coveo JavaScript Search Framework component in Sitecore using the Coveo Hive framework.

Overview

There are a few components required to have a complete implementation:

Each part will be covered in its own section.

Creating a Template Item

Coveo Hive uses Data Sources to give properties to the components.

You need to create a new template in Sitecore that will hold all the properties that can be defined by a developer or integrator in the Experience Editor.

Creating the ModelProperties Class

This class will be used by the Coveo Hive framework to read the properties from the template, and in a second step, to generate the properties that will be used by the Coveo JavaScript Search Framework.

The IModelProperties extends two interfaces:

  • IReadableModel , which is used to tag classes that have properties that can be read from Sitecore.

  • IWriteableModel , which is used to tag classes that have properties that can be written for the Coveo JavaScript Search Framework.

A ModelProperties class looks like the following example, which is the Pager’s ModelProperties class.

public class PagerProperties : IModelProperties
{
    [SitecoreProperty("EnableNavigationButton")]
    [SearchUiProperty]
    public bool? EnableNavigationButton { get; set; }

    [SitecoreProperty("NumberOfPages")]
    [SearchUiProperty]
    public int? NumberOfPages { get; set; }

    [SitecoreProperty("MaximumNumberOfResultsFromIndex")]
    [SearchUiProperty]
    public int? MaximumNumberOfResultsFromIndex { get; set; }
}

SitecoreProperty

SitecoreProperty is an attribute used to describe which Sitecore field to be read from the Data Source.

In the EnableNavigationButton case, the framework will read the EnableNavigationButton field from the Data Source, and set its value in the PagerProperties EnableNavigationButton.

SearchUiProperty

SearchUiProperty is an attribute used to describe how to serialize the value for the Coveo JavaScript Search Framework.

In the EnableNavigationButton case, the framework will write the key data-enable-navigation-button with the value set by the SitecoreProperty.

Nullable Properties

Most properties defined in ModelProperties classes are nullable.

When the value is null, the SearchUiProperty serializer will not output any key and value for this property. This allows you to use the default value from Coveo JavaScript Search Framework, but still define a value when needed.

Here are some ways to front null types in Sitecore:

  • If the field is a Boolean field, you need the Nullable Boolean field type. This will output one of those three field values: default, true, false.

  • If the field is a numeric or float field, you can use any standard numeric field type. An empty field value will be converted to null, and a numeric value will be used as it is.

  • If the field is a string field, there’s no way to have a nullable string in C#, so you must put string. The property won’t be output if the field value is empty.

Model

To front a model that can exploit the ModelProperties, you need to create a class that inherits Coveo Hive’s BaseModelWithProperties<T>.

Here is a simple example of the PagerModel:

public class PagerModel : BaseModelWithProperties<PagerProperties>
{
}

This model exposes two important properties:

public PagerProperties Properties { get; }

public IDictionary<string, string> RawProperties { get; }
  • Properties is an object matching all the values that were read from Sitecore using the SitecoreProperty attributes.

  • RawProperties is a dictionary containing all the key-value pairs that were serialized from the PagerProperties using SearchUiProperty attributes.

These two are used in the renderings to easily configure the components and use the properties that we need.

Adding Validation for the Model

You can execute code after the serialization is done by overriding the OnPropertiesInitialized method in the model.

protected override void OnPropertiesInitialized()
{
    AddOnValidationHandler(() => new ComponentWithDataSourceValidator(this));
}

AddOnValidationHandler is a method that takes a validation class that implements IComponentModelValidator.

In this case, ComponentWithDataSourceValidator ensures that a Data Source is set when the page is rendered.

If no Data Source is defined, an error is added to the error report that you can render in your .cshtml rendering file.

Rendering File

Coveo Hive framework provides some helpers to insert custom logic that’s common between many components.

First, create a simple .cshtml file for your component and insert the following code. This example will use CoveoPager.

<div class="CoveoPager" data-number-of-pages="3"></div>
Important

A component in the Coveo JavaScript Search Framework typically looks like the previous code block.

However, this component is static, therefore not driven by Sitecore properties. Replace all the data- attributes with a loop that uses the RawProperties dictionary:

@model Custom.Coveo.PagerModel

<div class="CoveoPager"
    @foreach (var property in @Model.RawProperties) {
        @: data-@(property.Key)='@(property.Value)'
    }>
</div>

This loop will only output the properties that were set in the rendering’s Data Source. null properties won’t be output at all here, leaving only the important attributes in the DOM.

If the component has an error and displays nothing, it will be completely invisible to the end user in the Experience Editor. The following helper makes it so the component is always visible:

@using Coveo.UI.Components
@using Coveo.UI.Components.Extensions
@model Custom.Coveo.PagerModel

<div>
    @Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName())
    <div class="CoveoPager"
        @foreach (var property in @Model.RawProperties) {
            @: data-@(property.Key)='@(property.Value)'
        }>
    </div>
</div>

Html.Coveo().GetViewName() fetches the current view name. You can replace it with a string value, which will be shown only in the Experience Editor.

Next, you might want to allow developers to see the attributes output by the component. The following extension shows a simple table with the content of the RawProperties dictionary:

@using Coveo.UI.Components
@using Coveo.UI.Components.Extensions
@model Custom.Coveo.PagerModel

<div>
    @Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName())
    @Html.Partial(Partials.DEBUG_INFORMATION, Model)
    <div class="CoveoPager"
        @foreach (var property in @Model.RawProperties) {
            @: data-@(property.Key)='@(property.Value)'
        }>
    </div>
</div>

The base model also offers validation mechanisms. You can implement validation to output different markups when the component is in error:

@using Coveo.UI.Components
@using Coveo.UI.Components.Extensions
@model Custom.Coveo.PagerModel

<div>
    @Html.Coveo().RenderErrorSummary(Model.ValidateModel())

    @if (Model.IsConfigured) {
        @Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName())
        @Html.Partial(Partials.DEBUG_INFORMATION, Model)
        <div class="CoveoPager"
            @foreach (var property in @Model.RawProperties) {
                @: data-@(property.Key)='@(property.Value)'
            }>
        </div>
    }
</div>

@Html.Coveo().RenderErrorSummary(Model.ValidateModel()) renders a simple error report if the component failed some validations.

Important

This error report is only shown in the Experience Editor

@if (Model.IsConfigured) ensures that the component isn’t output when it has an error.

Creating the Rendering Items in Sitecore

First, create a model item that references your newly created model.

Then, create a rendering item. There are many things that you must configure on it:

  • Model

  • Data Source Template

  • Data Source Location (optional)

To fully integrate this rendering in the standard Search Interface placeholder, follow the steps in Insert Custom Components in an Existing Search Interface