Form Builder

TsgcHTMLComponent_FormBuilder: a visual form designer that runs in the browser, so the users of your application design their own forms. What they publish is a regular TsgcHTMLComponent_Form, with its validation rules, input masks, conditional fields and live validation, in Delphi, C++ Builder and .NET.

TsgcHTMLComponent_FormBuilder

Link it to a TsgcHTMLComponent_Form and render it. Users drag fields from a toolbox onto a 12 column canvas, set them up in an inspector and press Save. OnSave hands you the definition as JSON to store, and with AutoApply the linked form shows the new design at once.

Component class

TsgcHTMLComponent_FormBuilder, which edits the definition of a linked TsgcHTMLComponent_Form

Renders

A toolbox, a design canvas, an inspector, a preview and a JSON view, in plain JavaScript and CSS with no external library

Languages

Delphi, C++ Builder, .NET

The builder edits the definition of the linked form. OnSave receives the JSON to store, and the public page loads it into a form of its own with LoadFromJSON. On submit, Validate checks the posted values and GetValuesJSON returns them as one typed JSON object.

uses
  sgcHTML_Component_Form, sgcHTML_Component_FormBuilder;

// On the form: a TsgcHTMLComponent_Form (Form1) and a
// TsgcHTMLComponent_FormBuilder (FormBuilder1) with Form = Form1

procedure TMainModule.FormBuilder1Save(Sender: TObject; const aJSON: string;
  var aAccept: Boolean; var aErrorMessage: string);
begin
  // aJSON is the normalized definition, already checked by the server
  StoreDefinition('contact', aJSON);   // your own store: a file, a table
end;

// The public page: a form per request, loaded from the stored design
function TMainModule.ContactPage: string;
var
  oForm: TsgcHTMLComponent_Form;
begin
  oForm := TsgcHTMLComponent_Form.Create(nil);
  try
    oForm.Action := '/f/contact';
    oForm.LoadFromJSON(ReadDefinition('contact'));
    Result := oForm.HTML;
  finally
    oForm.Free;
  end;
end;

// On submit: validate, then keep the typed values
function TMainModule.ContactPost(const aParams: TStrings): string;
var
  oForm: TsgcHTMLComponent_Form;
  oErrors: TStringList;
begin
  oForm := TsgcHTMLComponent_Form.Create(nil);
  oErrors := TStringList.Create;
  try
    oForm.LoadFromJSON(ReadDefinition('contact'));
    if oForm.Validate(aParams, oErrors) then
    begin
      StoreResponse('contact', oForm.GetValuesJSON(aParams));
      Result := ThankYouPage;
    end
    else
      Result := oForm.GetValidationResponse(oErrors);
  finally
    oErrors.Free;
    oForm.Free;
  end;
end;
@* Views/Forms/Builder.cshtml: the designer of one form *@
@model FormsModel

<sgc-form-builder name="builder" form="@Model.Form"
                  max-fields="50" css-height="720px"
                  on-save="Model.SaveDefinition" />
using esegece.sgcWebSockets;

// OnSave of the builder: aJSON is the normalized definition
public void SaveDefinition(object Sender, string aJSON, ref bool aAccept,
    ref string aErrorMessage)
{
    store.Save("contact", aJSON);
}

// The public form, POST /f/contact
var form = new TsgcHTMLComponent_Form();
form.Action = "/f/contact";
form.LoadFromJSON(store.Load("contact"));

var fields = Request.Form.Select(f => f.Key + "=" + f.Value).ToList();
var errors = new List<string>();
if (form.Validate(fields, errors))
    responses.Add("contact", form.GetValuesJSON(fields));

string schema = form.GetJSONSchema();   // JSON Schema 2020-12 of the data

What your users get

A designer for people who are not developers, and a form that behaves exactly like one you wrote in code.

Toolbox and canvas

The toolbox groups the fields into Basic, Choices, Advanced and Layout. Drag a field onto the canvas, or press Enter to add it after the selection. The canvas is a 12 column grid with a live look of the real controls: set a width of 3, 4, 6, 8, 9 or 12 columns, move a field by dragging it or with Alt+Up and Alt+Down, duplicate it or delete it. Undo and Redo work with Ctrl+Z and Ctrl+Y.

Inspector

The Field tab sets the label, a name generated from the label and kept unique, placeholder, help text, default value, required, read only, the options one per line, min and max, rows and the input mask. The Form tab sets the title, the description, a vertical or horizontal layout, the submit text and the reset button.

Validation rules

Each field takes a list of rules: length, range, pattern, email and custom, each with its own error message. They are the rules of TsgcHTMLComponent_Form, so the published form validates in the browser, with LiveValidation while the user types, and again on the server with Validate.

Conditional fields

Show a field only while an earlier field equals, does not equal or contains a value, is empty or not empty, or is greater or less than a number. The browser and the server apply the same rules: a hidden field is not posted, a required field hidden by its condition never fails, and a field that depends on a hidden field is hidden too.

18 field types

Text, email, password, number, textarea, select, radio, checkbox, switch, date, time, color, range, file and hidden, plus heading, paragraph and divider to lay the form out. FieldTypes sets which of them the toolbox offers.

Preview and JSON

Preview renders the design on the server as a real form with the look of the linked one, so its validation, masks and conditions run, and submitting it never posts. The JSON view shows the definition to view, copy, edit and apply. ShowPreview and ShowJSON turn the views on or off.

Templates

Templates holds one Caption=JSON line per template, and the toolbar offers them to start a new form from. New asks before it discards unsaved changes, and leaving the page with unsaved changes warns too.

Accessibility

Every action works from the keyboard. The toolbox and the canvas are WAI-ARIA listboxes, and a polite live region announces added, deleted, moved and saved fields and errors. The builder follows the page theme (data-bs-theme), mirrors itself under dir="rtl" and respects reduced motion.

Key properties, methods & events

The members you reach for most often.

Form and AutoApply

Form is the TsgcHTMLComponent_Form being designed. With AutoApply (on by default) a save loads the new definition into it inside Form.Lock, so a page that renders the form at the same time never sees half a design. ReadOnly shows the design and refuses Save.

OnSave

OnSave(Sender, aJSON, aAccept, aErrorMessage) receives the normalized definition: the posted JSON loaded into a scratch form and written back. Store it where you keep your data. Set aAccept to False to refuse it, with your own text in aErrorMessage.

Per user designs

OnGetForm(Sender, aForm) returns the form of the user behind the request. It is called at render time and on every request, and the builder never frees the form you return. The builder keeps no state between requests, so one component serves every user.

Security

The browser checks the names and the limits before it posts, and the server checks every posted definition again: its size against MaxSize (256 KB by default), the number of fields against MaxFields (100 by default), the field types, names that are valid and unique, the column spans, the rules and the conditions. A definition that fails is refused with the reason, before OnSave runs.

The definition JSON

SaveToJSON and LoadFromJSON on the form write and read the definition: the title, description, layout, buttons and fields, with their rules and conditions. Delphi and .NET write it byte for byte the same, so a design saved by one loads in the other. LoadFromJSON also reads the field array of LoadFieldsFromJSON.

JSON Schema and typed values

GetJSONSchema exports a JSON Schema 2020-12 of the submitted data, with types, formats, options, limits and the required fields. GetValuesJSON(aParams) returns the posted values as one JSON object in field order: numbers as numbers, checkbox and switch as true or false, and the fields hidden by their condition left out.

Without a server event

The builder posts to the component events endpoint of the HTMX engine, or to ActionURL. Without either, it still designs, and Save dispatches the DOM event sgc-form-builder-save on the builder with the JSON in its detail. With a URL the event follows a successful save too.

ASP.NET Core

In a Razor view, the <sgc-form-builder> Tag Helper renders the builder, and its save and preview requests are answered by the sgcHTML middleware of UseSgcHtml. The events are C# handlers, and the form it edits is the same TsgcHTMLComponent_Form class.

The demo

Demos\60.HTML\01.RunTime\34.FormBuilder is sgc Forms Studio, a server on port 8136 with four forms that also serve as templates: an event registration, a customer survey, a job application and an IT support request. Each form has a public page with live validation and a responses page with a grid, a chart, an Excel export and the JSON Schema. The design time, Lazarus and .NET versions mirror it.

Keep exploring

Try It OnlineSee it in the Form Builder demo, running live on the eSeGeCe demo server.
Online HelpFull API reference and usage guide for this component.
Form ComponentThe form the builder designs: fields, layouts, rules and dataset binding.
All sgcHTML ComponentsBrowse the full feature matrix of 80+ components.
Download Free TrialThe 30-day trial ships the 60.HTML demo projects.
PricingSingle, Team and Site licenses with full source code.
Best value: All-AccessEvery eSeGeCe product, Premium Support included, from €1,059/year.
See All-Access pricing

Ready to Get Started?

Download the free trial and start building web UIs in Delphi, C++ Builder and .NET.