--- title: Integrate a custom component in Sitecore using the Coveo Hive Framework slug: '2349' canonical_url: https://docs.coveo.com/en/2349/ collection: coveo-for-sitecore-v5 source_format: adoc --- # Integrate a custom component in Sitecore using the Coveo Hive Framework > **Legacy feature** > > The Coveo Hive Framework is now in maintenance mode and is no longer recommended for new implementations. > > To build new search experiences, use one of Coveo's more modern, lightweight, and responsive libraries. > To get started, see the [Build search](https://docs.coveo.com/en/2473/) article. 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: * [Template item used as Data Sources](#creating-a-template-item) * xref:creating-the-modelproperties-class,ModelProperties class] * [Model](#model) * [Rendering file](#rendering-file) * [Rendering item](#creating-the-rendering-items-in-sitecore) 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 must 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. [source,c#] ``` 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`, create a class that inherits Coveo Hive's `BaseModelWithProperties`. Here is a simple example of the `PagerModel`: [source,c#] ``` public class PagerModel : BaseModelWithProperties { } ``` This model exposes two important properties: [source,c#] ``` public PagerProperties Properties { get; } public IDictionary 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. [source,c#] ``` 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`. ```html
``` > **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: ```html @model Custom.Coveo.PagerModel
``` 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: ```html @using Coveo.UI.Components @using Coveo.UI.Components.Extensions @model Custom.Coveo.PagerModel
@Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName())
``` `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: ```html @using Coveo.UI.Components @using Coveo.UI.Components.Extensions @model Custom.Coveo.PagerModel
@Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName()) @Html.Partial(Partials.DEBUG_INFORMATION, Model)
``` The base model also offers validation mechanisms. You can implement validation to output different markups when the component is in error: ```html @using Coveo.UI.Components @using Coveo.UI.Components.Extensions @model Custom.Coveo.PagerModel
@Html.Coveo().RenderErrorSummary(Model.ValidateModel()) @if (Model.IsConfigured) { @Html.Partial(Partials.EDIT_TITLE, Html.Coveo().GetViewName()) @Html.Partial(Partials.DEBUG_INFORMATION, Model)
}
``` `@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. Configure the following fields 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](https://docs.coveo.com/en/2340/)