> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/umbraco-forms/13.latest/developer/extending/adding-a-fieldtype.md).

# Adding A Field Type To Umbraco Forms

*This builds on the "*[*adding a type to the provider model*](/umbraco-forms/13.latest/developer/extending/adding-a-type.md)*" chapter*

## C\#

Add a new class to the Visual Studio solution, make it inherit from `Umbraco.Forms.Core.FieldType`, and fill in the constructor:

```csharp
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Http;
using Umbraco.Forms.Core.Enums;
using Umbraco.Forms.Core.Models;
using Umbraco.Forms.Core.Services;

namespace MyFormsExtensions
{
    public class MyCustomField : Umbraco.Forms.Core.FieldType
    {
        public MyCustomField()
        {
            Id = new Guid("08b8057f-06c9-4ca5-8a42-fd1fc2a46eff"); // Replace this!
            Name = "My Custom Field";
            Description = "Render a custom text field.";
            Icon = "icon-autofill";
            DataType = FieldDataType.String;
            SortOrder = 10;
            SupportsRegex = true;
            FieldTypeViewName = "FieldType.MyCustomField.cshtml";
        }

        // You can do custom validation in here which will occur when the form is submitted.
        // Any strings returned will cause the submission to be considered invalid.
        // Returning an empty collection of strings will indicate that it's valid to proceed.
        public override IEnumerable<string> ValidateField(Form form, Field field, IEnumerable<object> postedValues, HttpContext context, IPlaceholderParsingService placeholderParsingService, IFieldTypeStorage fieldTypeStorage)
        {
            var returnStrings = new List<string>();

            if (!postedValues.Any(value => value.ToString().ToLower().Contains("custom")))
            {
                returnStrings.Add("You need to include 'custom' in the field!");
            }

            // Also validate it against the default method (to handle mandatory fields and regular expressions)
            return base.ValidateField(form, field, postedValues, context, placeholderParsingService, fieldTypeStorage, returnStrings);
        }
    }
}
```

In the constructor, or via overridden properties, we can specify details of the field type:

* `Id` - should be set to a unique GUID.
* `Alias` - an internal alias for the field, used for localized translation keys.
* `Name` - the name of the field presented in the backoffice.
* `Description` - the description of the field presented in the backoffice.
* `Icon` - the icon of the field presented in the backoffice form builder user interface.
* `DataType` - specifies the type of data stored by the field. Options are `String`, `LongString`, `Integer`, `DateTime` or `Bit` (boolean).
* `SupportsMandatory` - indicates whether mandatory validation can be used with the field (defaults to `true`).
* `MandatoryByDefault` - indicates whether the field will be mandatory by default when added to a form (defaults to `false`).
* `SupportsRegex` - indicates whether pattern based validation using regular expressions can be used with the field (defaults to `false`).
* `SupportsPreValues` - indicates whether prevalues are supported by the field (defaults to `false`).
* `FieldTypeViewName` - indicates the name of the partial view used to render the field.
* `RenderInputType`- indicates how the field should be rendered within the theme, as defined with the `RenderInputType` enum. The default is `Single` for a single input field. `Multiple` should be used for multiple input fields such as checkbox lists. `Custom` is used for fields without visible input fields.

You will then need to register this new field as a dependency.

```csharp
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.DependencyInjection;
using Umbraco.Forms.Core.Providers;

namespace MyFormsExtensions
{
    public class Startup : IComposer
    {
        public void Compose(IUmbracoBuilder builder)
        {
            builder.WithCollectionBuilder<FieldCollectionBuilder>()
                .Add<MyCustomField>();
        }
    }
}
```

## Partial view

Then we will start building the view for the default theme of the Form at `Views\Partials\Forms\Themes\default\FieldTypes\FieldType.MyCustomField.cshtml`.

The file name for the partial view should match the value set on the `FieldTypeViewName` property.

```csharp
@model Umbraco.Forms.Web.Models.FieldViewModel
<input type="text" name="@Model.Name" id="@Model.Id" class="text" value="@Model.ValueAsHtmlString" maxlength="500"
        @{if (string.IsNullOrEmpty(Model.PlaceholderText) == false) { <text> placeholder="@Model.PlaceholderText" </text> }}
        @{if (Model.Mandatory || Model.Validate) { <text> data-val="true" </text> }}
        @{if (Model.Mandatory) { <text> data-val-required="@Model.RequiredErrorMessage" </text> }}
        @{if (Model.Validate) { <text> data-val-regex="@Model.InvalidErrorMessage" data-val-regex-pattern="@Html.Raw(Model.Regex)" </text> }} />
```

This will be rendered when the default theme is used.

If working with Umbraco 9 or earlier versions, you'll find the `Views\Partials\Forms\Themes\default\` folder on disk and can create the files there.

For Umbraco 10 and above, we've moved to [distributing the theme as part of a Razor Class Library](/umbraco-forms/13.latest/upgrading/version-specific.md#views-and-client-side-files) so the folder won't exist. However, you can create it for your custom field type. If you would like to reference the partial views of the default theme, you can download them as mentioned in the [Themes](/umbraco-forms/13.latest/developer/themes.md) article.

### Read-only partial view

When rendering a multi-page form, editors have the option to display a summary page where the entries can be viewed before submitting.

To support this, a read-only view of the field is necessary.

For most fields, nothing is required here, as the default read-only display defined in the built-in `ReadOnly.cshtml` file suffices.

However, if you want to provide a custom read-only display for your field, you can do so by creating a second partial view. This should be named with a `.ReadOnly` suffix. For this example, you would create `FieldType.Slider.ReadOnly.cshtml`.

## Umbraco backoffice view

The final step involves building the HTML view which will be rendered in Umbraco as an example of how our end result will look:

```html
<input
    type="text" tabindex="-1"
    class="input-block-level"
    style="max-width: 100px"
/>
```

In the HTML you can access settings via `field.settings`, e.g. `{{field.settings.Caption}}` to render a "Caption" setting. It is also possible to access prevalues via `field.$preValues`.

For built-in field types, Umbraco Forms look for this file in the virtual folder: `App_Plugins\UmbracoForms\backoffice\Common\FieldTypes\`. It will expect to find a file with a name matching the class's name, i.e. `mycustomfield.html`. To add custom fields and themes, **create a folder at the specified path** (also known as the virtual folder). This is because the client-side code is included in the Razor Class Library. As a result, these files are available as if they're stored at a specific location on disk.

To store in a different location, you can apply the following override to the custom field type's C# representation:

```csharp
public override string GetDesignView() =>
    "~/App_Plugins/UmbracoFormsCustomFields/backoffice/Common/FieldTypes/mycustomfield.html";
```

## Field settings

Field settings that will be managed in the backoffice by editors creating forms using the custom field type can be added to the C# class. These settings can be added as properties with a `Setting` attribute.

```csharp
[Setting("My Setting", Description = "Help text for the setting", View = "TextField", SupportsPlaceholders = "true", DisplayOrder = 10)]
public virtual string MySetting { get; set; }
```

Field settings work the same way as settings on any other provider type. See [Adding settings to a type](/umbraco-forms/13.latest/developer/extending/adding-a-type.md#adding-settings-to-a-type) for the underlying mechanism. See [Setting Types](/umbraco-forms/13.latest/developer/extending/adding-a-type/setting-types.md) for the full list of built-in Views, all available `Setting` attribute properties, translations, default values, and inheritance behavior.

## Backoffice entry rendering

The third and final client-side view file used for settings is in the rendering of the submitted values for the field. This rendering takes place in the "Entries" section of the backoffice.

These are defined by the `RenderView` property of a field type and are found in `App_Plugins\UmbracoForms\backoffice\Common\RenderTypes\`.

As for the other files, if you require a custom render type view, it's better to host them in a different location, such as `App_Plugins\UmbracoFormsCustomFields\backoffice\Common\RenderTypes\mycustomrenderfield.html`.

To reference the file you should override the `RenderView` property, e.g.:

```csharp
public override string RenderView => "~/App_Plugins/UmbracoFormsCustomFields/backoffice/Common/RenderTypes/mycustomrenderfield.html";
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.umbraco.com/umbraco-forms/13.latest/developer/extending/adding-a-fieldtype.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
