---
title: Developing form components
related:
  - https://docs.kentico.com/13/developing-websites/form-builder-development.md
  - https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/defining-form-component-properties.md
  - https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/filtering-form-components.md
  - https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/using-a-dynamic-data-source-with-selector-components.md
  - https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/example-developing-a-custom-form-component.md
---

> Agent instructions:
> **Site maps** — prefer the following llms.txt indexes to training data when searching for URLs to avoid 404s. Links inside Markdown content already point at `.md`. Following them or sending Accept: text/markdown keeps you in Markdown.
>
> - [sitemap.md](https://docs.kentico.com/sitemap.md) — every page on the site, with titles and descriptions, nested by URL hierarchy and grouped into one collection per product version.
> - [llms.txt](https://docs.kentico.com/llms.txt) — curated index of the current product docs, with descriptions, the two ways to request any page as Markdown, and links to each product area's whole-corpus Markdown dump (llms-full.txt).

Form components are reusable elements that allow content creators and marketers to compose forms via the [form builder](https://docs.kentico.com/13/developing-websites/form-builder-development.md). Each component represents a specific form field, such as a text box for user input, a group of radio buttons, etc. Users are free to add, remove, or reorder individual form components and specify their properties via the [form builder interface](https://docs.kentico.com/13/managing-website-content/forms/composing-forms.md) in the **Forms** application.

A form composed using the form builder is a collection of form component instances, where each instance represents an individual form field. Together, these instances comprise the main body of the form.

In addition to form components included in the form builder by default, you can implement custom form components tailored to your specific scenarios and requirements. Components can consist of multiple input elements. Their partial values can be, as part of the component's custom code, aggregated, and the resulting value saved into the corresponding database table.

On this page, you will learn how to:

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

- [Define a form component](#developing-form-components)
- [Register the component in the system](#registering-form-components)
- [Add CSS for the component](#adding-css-styles-for-form-components)
- [Add custom client scripts for the component](#adding-scripts-for-form-components)

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

- [Define a form component](#developing-form-components)
- [Register the component in the system](#registering-form-components)
- [Add scripts and styles for the component](#adding-scripts-and-styles-for-form-components)

<!-- dev-model:core end -->

## Developing form components

All form components need to inherit from the **FormComponent** class, where the **TProperties** generic parameter needs to be a class derived from **FormComponentProperties**, and the _TValu&#x65;_&#x74;ype needs to be identical for both classes. Each component also requires a corresponding view template that describes how its input elements are rendered.

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

> **Note:** **MVC Areas**
>
> Form components are designed to be used in the global scope and therefore must be registered in the application root of your live site project (not in an MVC Area). Registering form components in MVC Areas may lead to unexpected behavior.

> **Tip:** See [Example - Developing a custom form component](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/example-developing-a-custom-form-component.md) for a full step-by-step example demonstrating how to implement and register a form component in the system.

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

> **Note:** **Areas**
>
> Form sections are designed to be used in the global scope and their code files must be placed in the application root of your Core project (not in an [Area](https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/areas)). Creating sections in Areas may lead to unexpected behavior.

<!-- dev-model:core end -->

Follow these steps to create a form component:

1. Open your live site project in Visual Studio.

2. Create a form component class that inherits from **FormComponent**.
   - This class defines properties used for model binding from the component's input elements.
   - The _TValue_ generic determines the data type of the form component's overall value (e.g., a basic data type such as _string_, _int_ or _bool_).

3. Create a form component properties class that inherits from **FormComponentProperties**.

   - This class is used to define the properties of the form component (i.e., the component's underlying database column type, constraints, and other configuration options. See [Defining form component properties](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/defining-form-component-properties.md)).
   - The _TValue_ generic needs to match the data type of the corresponding form component.

   > **Tip:** We recommend storing the classes of form components under a dedicated _\~/Models/FormComponents_ folder.

4. In the model class derived from _FormComponent_:

   1. Substitute the generic _TProperties_ parameter with the type derived from _FormComponentProperties_.
   2. Define properties used to pass values from the form component's input elements to Xperience for data binding, and decorate them with the **BindableProperty** attribute.
   3. Override the following methods:
      - **GetValue** – gets the value of the form field instance passed from a view where the instance is rendered. Can be used to compose multiple bindable properties into a single value.
      - **SetValue** – sets the class's properties based on the value of the underlying form field instance.

   > **Note:** **Custom handling of server-side field value evaluation**
   >
   > By default, Xperience monitors all input elements of form fields that possess dependencies requiring server-side evaluation. Whenever the system detects a change in the value of such inputs, it automatically submits the form to the server for evaluation. This occurs, for example, when a user fills in a form field that has a [visibility condition](https://docs.kentico.com/13/developing-websites/form-builder-development/defining-field-visibility-conditions.md) associated with it (to check whether the depending field should be displayed or hidden).
   >
   > You may want to prevent the automatic evaluation in form components that construct their resulting value from multiple inputs (via the _GetValue_ method). In such components, it does not usually make sense to evaluate the component's resulting value until after the values for all of the component's partial inputs have been provided, as demonstrated, for example, in the sample [Rgb color selector component](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/example-developing-a-custom-form-component.md).
   >
   > If you wish to prevent Xperience from monitoring a form component:
   >
   > 1. Override the virtual **CustomAutopostHandling** property, inherited from the **FormComponent** base class, and set it to **true**, which ensures Xperience does not automatically observe any of the component's inputs.
   > 2. Manually submit the form to the server for evaluation by calling the **window.kentico.updatableFormHelper.updateForm** JavaScript function with the **this.form** argument, i.e. **window.kentico.updatableFormHelper.updateForm(this.form)**, within your JavaScript code or within an element's [HTML event attribute](https://www.w3schools.com/tags/ref_eventattributes.asp) (most commonly **onchange**, or **onclick**). The form is submitted only when the function is executed, leaving it up to the component's developer to ensure this happens at an opportune moment. For example, when all the required values have been provided.
   >
   > For a sample implementation, please refer to [Example - Developing a custom form component](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/example-developing-a-custom-form-component.md).

   4. (Optional) Override the virtual **LabelForPropertyName** member to specify which property the 'for' attribute of the field's  element targets. By default, the value of this property is set to the name of the first bindable property found within the form component class.

   ```csharp

       public class CustomFormComponent : FormComponent<CustomFormComponentProperties, string>
       {
           public const string IDENTIFIER = "CustomFormComponent";

           // Specifies the property is used for data binding by the form builder
           [BindableProperty]
           // Used to store the value of the input field of the component
           public string Value { get; set; }

           // Gets the value of the form field instance passed from a view where the instance is rendered
           public override string GetValue()
           {
               return Value;
           }

           // Sets the default value of the form field instance
           public override void SetValue(string value)
           {
               Value = value;
           }
       }


   ```

5. In the class derived from _FormComponentProperties_:

   - Call the constructor of the base class and specify the data type of the underlying database column using the **FieldDataType** enumeration. For the list of available data types or to learn how to register custom data types suitable for your component, see [Managing field data types](https://docs.kentico.com/13/custom-development/managing-field-data-types.md).

     > **Note:** The base class constructor also takes the following optional parameters:
     >
     > - **size** – sets the size of the corresponding component's underlying database column.
     >
     > - **precision** – governs the number of digits floating point numbers stored in the database can contain.These parameters configure the underlying database column, and need to be specified when the data type of the form component requires it, for example:
     >
     > - Specify the _size_ parameter when defining components with the _FieldDataType.Text_ data type – _base(FieldDataType.Text, size: 200)_
     >
     > - Specify the _precision_ parameter when defining components with the _FieldDataType.Decimal_ data type – _base(FieldDataType.Decimal, precision: 10)_
   - _Override_ the **DefaultValue** property, used to _get_ or _set_ the default value of fields based on the form component.
     - Annotate the property with the [DefaultValueEditingComponentattribute](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/defining-form-component-properties.md) to specify the form component providing the default value editing interface in the form builder properties panel. For a full list of system form components, refer to [Reference - System form components](https://docs.kentico.com/13/developing-websites/form-builder-development/reference-system-form-components.md).
   - (Optional) Declare [additional properties ](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/defining-form-component-properties.md)the form component requires.

   ```csharp

           // Sets a custom editing component for the DefaultValue property
           // System properties of the specified editing component, such as the Label, Tooltip, and Order, remain set to system defaults unless explicitly set in the constructor
           [DefaultValueEditingComponent(TextInputComponent.IDENTIFIER)]
           public override string DefaultValue
           {
               get;
               set;
           }

           // Initializes a new instance of the CustomFormComponentProperties class and configures the underlying database field
           public CustomFormComponentProperties()
               : base(FieldDataType.Text, size: 200)
           {
           }


   ```

6. Create a new partial view used to render an instance of the form component and place it in the _\~/Views/Shared/FormComponents_ folder. Use a view name that matches the identifier assigned to the form component [upon its registration](#registering-form-components) and prefix it with the underscore (_'\_'_) character (to indicate a partial view according to best practices).

   > **Tip:** You can override the default system behavior and place views into custom locations by specifying an optional parameter during the [component registration](#registering-form-components).

   In the view:

   1. Retrieve the dictionary collection of system HTML attributes by calling the **ViewData.Kentico().GetEditorHtmlAttributes** extension method (from the _Kentico.Forms.Web.Mvc_ namespace). You can modify the collection to include additional attributes the component requires, such as CSS classes and data attributes. Ensure the collection is included in each input element as certain features, such as [visibility condition](https://docs.kentico.com/13/developing-websites/form-builder-development/defining-field-visibility-conditions.md) evaluation, may not work otherwise.
   2. Specify input elements for the component. If possible, use extension methods provided by the framework's **HtmlHelper** class to render individual inputs as they, by default, provide an easy way to merge additional HTML attributes and ensure the inputs contain fully qualified names, facilitating model binding.\
      If you need to write more complex inputs, we recommend writing an extension method that handles the creation of input elements via the **TagBuilder** class, which simplifies the definition of additional attributes and handles attribute encoding by default. To generate fully qualified names and identifiers for model binding, use the **Html.NameFor** and **Html.IdFor** extension methods, respectively. See [Example - Developing a custom form component](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-form-components/example-developing-a-custom-form-component.md) for an example implementation.

      > **Tip:** **Modal dialogs**
      >
      > You can also [implement modal dialogs](https://docs.kentico.com/13/developing-websites/page-builder-development/developing-modal-dialogs-for-builder-component-properties.md) to be able to handle more complex inputs in a new pop-up dialog.

   ```csharp title="_CustomFormComponent.cshtml"

   @using Kentico.Forms.Web.Mvc

   @* Gets a collection of system HTML attributes necessary for the correct functionality of the form component inputs *@
   @{
       IDictionary<string, object> htmlAttributes = ViewData.Kentico().GetEditorHtmlAttributes();
   }

   @model LearningKit.FormBuilder.FormComponents.CustomFormComponent

   @* Specifies additional HTML attributes of the form component. Checks for the existence of certain attributes in case
       the returned 'htmlAttributes' collection already contains them (e.g., when the component is rendered within
       the administration interface, where Xperience provides CSS classes to maintain the admin UI look and feel) *@
   @{
       if (htmlAttributes.ContainsKey("class"))
       {
           htmlAttributes["class"] += " myclass";
       }
       else
       {
           htmlAttributes["class"] = "myclass";
       }
   }

   @* Renders the input element for the 'Value' property of the form component *@
   @Html.TextBoxFor(m => m.Value, htmlAttributes)


   ```

7. (Optional) Write any required CSS and JavaScript code the component requires for its functionality. Place the script and style files into the _\~Content/FormComponents/_ folder. See [Adding CSS styles for form components](#adding-css-styles-for-form-components) and [Adding scripts for form components](#adding-scripts-for-form-components) for more information and recommended practices.

## Registering form components

To register a form component, annotate the class derived from _FormComponent_ with the **RegisterFormComponent** assembly attribute. This attribute ensures the component is recognized by the system and available for [use in the form builder](https://docs.kentico.com/13/managing-website-content/forms/composing-forms.md). When registering the component, specify the following parameters:

- **Identifier** – a _string_ identifier of the form component.

  > **Tip:** If you are planning to distribute your components, or are using components from third-party sources, consider specifying the identifier in a format that uniquely identifies your form component to avoid potential conflicts with identifier names. For example, use _CompanyName.ModuleName.ComponentName_.
- **FormComponentType** – the _System.Type_ of the form component class.
- **Name** – sets the name of the form component. Displayed when [adding form fields](https://docs.kentico.com/13/managing-website-content/forms/composing-forms.md) on the _Form builder_ tab in the administration interface.
- (Optional) **Description**– sets the description of the form component. Displayed when adding form fields on the _Form builder_ tab in the administration interface.
- (Optional) **IsAvailableInFormBuilderEditor**– determines if the form component can be added as a form field. _True_ by default. If set to _false_, the component can only be added via the [EditingComponent attribute](https://docs.kentico.com/13/developing-websites/form-builder-development/assigning-editing-components-to-properties.md).
- (Optional) **ViewName** – specifies the name of the view used to display the component, for example _CustomComponent_. If not set, the system searches for a corresponding _\_.cshtml_ view in the _\~/Views/Shared/FormComponents/_ folder.
- (Optional) **IconClass** – the font-icon assigned to the form component. Displayed in the component listing when adding new fields on the _Form builder_ tab. For a list of font icons available by default in the system, see the [Icon list](http://devnet.kentico.com/docs/icon-list/index.html).

  > **Tip:** **Localizing form component metadata**
  >
  > Both the **Name** and the **Description** of form components can be localized using resource string keys. See [Localizing builder components](https://docs.kentico.com/13/multilingual-websites/setting-up-a-multilingual-user-interface/localizing-builder-components.md).

You can see the registration of a sample form component of the _CustomFormComponent_ type in the code snippet below:

```csharp

// Registers a form component for use in the form builder
[assembly: RegisterFormComponent(CustomFormComponent.IDENTIFIER, typeof(CustomFormComponent), "Custom component", Description = "This is a custom form component.", IconClass = "icon-newspaper")]


```

The form component is now created and registered in the system. Users can include it when composing forms [using the form builder interface](https://docs.kentico.com/13/managing-website-content/forms/composing-forms.md).

<!-- dev-model:mvc start -->

**MVC 5 development model.** Applies only when building with ASP.NET MVC 5. If this page also covers ASP.NET Core, that version is in its own block.

## Adding CSS styles for form components

Use the following approach to add CSS styles for your form components:

- For **basic styles** that are required for the component to render correctly, create stylesheet files in sub-folders under the _**\~/Content/FormComponents**_  directory of your live site project (you may need to create the _FormComponents_ directory). Use sub-folders that match the identifiers of individual components.
- If you wish to provide additional styling for the Xperience **administration interface** (for example to ensure that components are in line with the overall look and feel of the admin UI), add another stylesheet file to the same directory with the _**.admin.css**_ extension.
- Any **site-specific styles** that finalize the live site design of the form component should be handled separately within the given site's main stylesheet.

  > **Tip:** Avoid potential conflicts between styles from other third-party form components by adding a unique prefix to your CSS classes and identifiers (for example, _#CompanyName-mid-button_) or employ similar measures to ensure their uniqueness.

The system automatically creates [bundles](https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification) containing all _.css_ files located under _\~/Content/FormComponents_ – one for general styles and another for the administration interface styles. The bundles are then linked in the following locations:

- When working with forms in the **Forms** application of the Xperience administration interface.
- The bundle containing general styles is linked on all pages with [page builder editable areas](https://docs.kentico.com/13/developing-websites/page-builder-development/creating-pages-with-editable-areas.md) (the page builder is used to display forms on the live site via the _Form_ widget).

The same bundles also contain styles added for [form sections](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-custom-form-layouts.md) in the _\~/Content/FormSections_ directory.

> **Note:** **CSS file order**
>
> Do not make any assumptions about the relative order of the source CSS in the resulting bundles – individual files contained in the bundle may or may not precede each other.

## Adding scripts for form components

If your form components require any JavaScript, place script files into sub-folders under the _**\~/Content/FormComponents**_ directory of your live site project (you may need to create the _FormComponents_ directory). Use sub-folders that match the identifiers of individual components or a _Shared_ sub-folder for assets used by multiple components.

The system automatically creates a [bundle](https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification) containing all _.js_ files located under _\~/Content/FormComponents_. The bundle is then linked in the following locations:

- When working with forms in the **Forms** application of the Xperience administration interface.
- On all pages with [page builder editable areas](https://docs.kentico.com/13/developing-websites/page-builder-development/creating-pages-with-editable-areas.md) (the page builder is used to display forms on the live site via the _Form_ widget).

The same bundle also contains script files added for [form sections](https://docs.kentico.com/13/developing-websites/form-builder-development/developing-custom-form-layouts.md) in the _\~/Content/FormSections_ directory.

### Initializing component scripts

In many cases, you will need to initialize your scripts from the views of form components (for example if you need to call a function on page load or register an event listener). For most types of page or element events, you can use [HTML Event Attributes](https://www.w3schools.com/tags/ref_eventattributes.asp) of elements in your views.

For scripts that you want to run on page load, you need to consider the following:

- The bundles containing your main scripts are added at the end of the HTML document's body tag, so they are not available in the component code during the page load process. A solution is to run the initialization script during the [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event.
- Components may be added dynamically after the page is loaded. In this case, the _DOMContentLoaded_ event has already occurred and will not fire again.

For example, the following script demonstrates how to reliably call a custom function on page load:

```js

if (document.readyState === "loading") {
    // Calls the function during the 'DOMContentLoaded' event, after the HTML document has been completely loaded
    document.addEventListener("DOMContentLoaded", function () {
        customFunction();
    });
} else { 
    // Calls the function directly in cases where the component is rendered dynamically after 'DOMContentLoaded' has occurred
    customFunction();
}

```

This approach ensures that the initialization script runs correctly when the form component is displayed on the live site, as well as in the form builder interface.

> **Note:** **Note**: Apart from initialization code, avoid linking or executing scripts directly within form component views – this could lead to duplicated scripts for forms that contain multiple fields based on the same component, or on pages with multiple forms.

### Using jQuery scripts

By default, Xperience links two system jQuery 3.5.1 [bundles](https://docs.microsoft.com/en-us/aspnet/mvc/overview/performance/bundling-and-minification) into the pages of the form builder interface.

You can disable the use of jQuery for the form builder by setting the **CMSBuilderScriptsIncludeJQuery** key to _false_ in the configuration file of your **live site project** (_appsettings.json_ or _web.config_). All default features remain functional without jQuery.

If you wish to use jQuery within your form components, but require a different version, you need to create your own bundle(s) with the corresponding paths:

- _\~/bundles/jquery_
- _\~/bundles/jquery-unobtrusive-ajax_ – bundle for using the [jquery.unobtrusive-ajax.js](https://www.nuget.org/packages/Microsoft.jQuery.Unobtrusive.Ajax/) JavaScript library (not to be confused with the _jquery.validate.unobtrusive.js_ library)

When you register a bundle with one of these paths, the form builder interface links your jQuery bundle instead of the corresponding system bundle.

> **Note:** **Important**: When you register a custom jQuery bundle, the system no longer links the default jQuery bundle on pages with [page builder](https://docs.kentico.com/13/developing-websites/page-builder-development.md) editable areas (the page builder is used to display forms on the live site via the _Form_ widget). You need to manually link your custom jQuery bundle on the given pages (either within the used layout or directly in the page's view).
>
> For more information, see [Creating pages with editable areas](https://docs.kentico.com/13/developing-websites/page-builder-development/creating-pages-with-editable-areas.md).

<!-- dev-model:mvc end -->

<!-- dev-model:core start -->

**ASP.NET Core development model.** Applies only when building with ASP.NET Core. If this page also covers MVC 5, that version is in its own block.

## Adding scripts and styles for form components

To add JavaScript and CSS styles required by your components, we recommend placing script and stylesheet files into sub-folders under:

- _**\~/wwwroot/FormBuilder/Public/**_ – scripts intended for both the live site and administration. Styles intended for the live site.
- _**\~/wwwroot/FormBuilder/Admin/**_ – scripts and styles intended for the administration interface. Note that the system already attempts to enforce a unified look and feel for components rendered in the form builder interface.

You can use sub-folders that match the identifiers of individual components, or a _Shared_ sub-folder for assets used by multiple components. Note that this recommendation only applies when using the default configuration of the bundling support provided by Xperience and may be different for your project. See [Bundling static assets of builder components](https://docs.kentico.com/13/developing-websites/developing-xperience-applications-using-asp-net-core/bundling-static-assets-of-builder-components.md).

> **Note:** **CSS notes**
>
> - Only use the specified directories to add **basic styles** that are required for the widget to render correctly. Any **site-specific styles** that finalize the live site design of the widget should be handled separately within the given site's main stylesheet.
> - To avoid potential conflicts between styles from other third-party components, we recommend adding a unique prefix to your CSS classes and identifiers (e.g., _#CompanyName-mid-button_), or use similar measures to ensure their uniqueness.

### Initializing component scripts

In many cases, you will need to initialize your scripts from the views of form components (for example if you need to call a function on page load or register an event listener). For most types of page or element events, you can use [HTML Event Attributes](https://www.w3schools.com/tags/ref_eventattributes.asp) of elements in your views.

For scripts that you want to run on page load, you need to consider the following:

- The bundles containing your main scripts are added at the end of the HTML document's body tag, so they are not available in the component code during the page load process. A solution is to run the initialization script during the [DOMContentLoaded](https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded) event.
- Components may be added dynamically after the page is loaded. In this case, the _DOMContentLoaded_ event has already occurred and will not fire again.

For example, the following script demonstrates how to reliably call a custom function on page load:

```js

if (document.readyState === "loading") {
    // Calls the function during the 'DOMContentLoaded' event, after the HTML document has been completely loaded
    document.addEventListener("DOMContentLoaded", function () {
        customFunction();
    });
} else { 
    // Calls the function directly in cases where the component is rendered dynamically after 'DOMContentLoaded' has occurred
    customFunction();
}

```

This approach ensures that the initialization script runs correctly when the form component is displayed on the live site, as well as in the form builder interface.

> **Note:** **Note**: Apart from initialization code, avoid linking or executing scripts directly within form component views – this could lead to duplicated scripts for forms that contain multiple fields based on the same component, or on pages with multiple forms.

<!-- dev-model:core end -->
