Disclaimer: This is based on a beta version of Episerver.Forms, so anything can change in the future. If stuff breaks after updating, you're going to have to deal with that yourself. 

Episerver provides you with a bunch of default form input elements. Textboxes, textareas, dropdown lists and number fields with suitable validators come as standard when you install the package. However, you might just need to create your own: Maybe your text field needs some funky autocomplete? Or maybe you need more markup around your field to guide your users properly? What about dynamically loaded data sources for a dropdown depending on the value in a textbox? All these things can be made.

1. Your custom form element type

Since form elements are based on blocks, you create them the same way as any form of IContent. Where you'd normally inherit from PageData or BlockData, you will now inherit from one of the classes in the EPiServer.Forms.Implementation.Elements or EPiServer.Forms.Implementation.Elements.BaseClasses namespaces. In my example, I'm going for a custom text box:

[ContentType(GUID = "95A98808-4BFC-43FE-B723-4FD2F7E0FF1A")]
public class CustomTextBoxElementBlock : TextboxElementBlock
{
    public virtual string HelpText { get; set; }
}

So, as you can see, it's just inheriting from the existing text box, and then I'm adding an additional property, just like on other IContent types.

You currently have to provide a translated name of your content type, or you won't be able to add it to your form. This should be done by putting it in one of your language files, along with your other translations:

<languages>
  <language name="English" id="en">
    <contenttypes>
      <customtextboxelementblock>
        <name>My custom text box</name>
        <description />
      </customtextboxelementblock>
    </contenttypes>
  </language>
</languages>

2. Your view

The current version of the Forms module does not support inheriting the default views, so you'll have to create your own. This will probably be the case most of the time anyways.

@model CustomTextBoxElementBlock

<div class="Form__Element FormTextbox" data-epiforms-element-name="@Model.FormElement.Code">
    <label for="@Model.FormElement.Guid">
        My label
    </label>
    <input type="text" name="@Model.FormElement.Code" class="FormTextbox__Input" id="@Model.FormElement.Guid" @Model.FormElement.AttributesString/>

    <p>@Html.PropertyFor(x => x.HelpText)</p>

    <span data-epiforms-linked-name="@Model.FormElement.Code" class="Form__Element__ValidationError" style="display: none;">*</span>
</div>

Apart from rendering the HelpText property, this seems to be the absolute minimum required to render a custom input field properly. The class names, surrounding container and data-attributes are required for the built in client side validators to work. Apart from letting those stay, you can fiddle about with element types and adding stuff if you need to. Custom client side magic will have to be added separatly, unless you want it in the same file.

Wishes going forward

Since this is currently a beta module, here is some input for you guys making it: