Form Builder

Form Builder

Typed field definitions, server-side validatie, en conditionals die via data-attributen worden doorgegeven aan form-enhanced.js.

Opent een full-screen overlay met de huidige FormFactory-JSON als startpunt.

Demo formulier

Account type
Zoals ingeschreven bij de KvK
8 cijfers

Hoe werkt het?

Field definitie

TextField::create('voornaam')
    ->label('Voornaam')
    ->placeholder('Jan')
    ->addValidator(new RequiredValidator())
    ->addValidator(new MinLengthValidator(2))

Naast elkaar (gelijke kolommen)

FieldRow::of(
    SelectField::create('land')->label('Land'),
    TextField::create('telefoon')->label('Telefoonnummer'),
)

Naast elkaar (eigen verhoudingen)

// Land krijgt 2/3, telefoon 1/3
FieldRow::of($land, $telefoon)
    ->widths([2, 1])

// 3 gelijke kolommen
FieldRow::of($dag, $maand, $jaar)

Rij conditioneel verbergen

FieldRow::of($kvk, $btw)
    ->showWhen(
        ConditionalRule::whenEqual('type', 'zakelijk')
    )

Conditional (veld-niveau)

TextField::create('bedrijfsnaam')
    ->showWhen(
        ConditionalRule::whenEqual('type', 'zakelijk')
    )

Server-side validatie

$result = $form->process($_POST);

if ($result->isValid()) {
    $naam = $result->value('voornaam');
} else {
    $errors = $result->errorsFor('voornaam');
}

Responsive

/* CSS: één media query, alle rijen stappen
   automatisch op smal scherm */
@media (max-width: 640px) {
  .form-row {
    grid-template-columns: 1fr !important;
  }
}

Conditional JSON

De data-conditional attributen die form-enhanced.js leest:

  • bedrijfsnaam: {"field":"type","operator":"equal","value":"zakelijk"}
  • kvk: {"field":"type","operator":"equal","value":"zakelijk"}
  • btw_nummer: {"logic":"and","rules":[{"field":"type","operator":"equal","value":"zakelijk"},{"field":"land","operator":"notequal","value":"nl"}]}

FormFactory: JSON → Form

De CMS-kant slaat een formulier op als JSON in de database. FormFactory::fromJson() vertaalt dat naar hetzelfde Form-object als handgeschreven PHP-code. De renderer merkt het verschil niet.

Geparsed formulier

Exact hetzelfde als handgeschreven code — zelfde renderer, zelfde validatie, zelfde conditionals.

Type aanvraag
Zoals ingeschreven bij de KvK

JSON (CMS-opslag)

Dit is wat het CMS wegschrijft in de database. De website leest dit en bouwt het formulier.

Zo simpel is de website-code

$form = FormFactory::fromJson($jsonUitDatabase);
$html = (new FormRenderer())->render($form, $result);

JSON schema

{
    "id": "cms-offerte",
    "action": "\/form-builder",
    "elements": [
        {
            "type": "row",
            "widths": [
                1,
                1
            ],
            "fields": [
                {
                    "type": "text",
                    "name": "cms_voornaam",
                    "label": "Voornaam",
                    "placeholder": "Jan",
                    "validators": [
                        {
                            "type": "required"
                        }
                    ]
                },
                {
                    "type": "text",
                    "name": "cms_achternaam",
                    "label": "Achternaam",
                    "validators": [
                        {
                            "type": "required"
                        }
                    ]
                }
            ]
        },
        {
            "type": "field",
            "field": {
                "type": "email",
                "name": "cms_email",
                "label": "E-mailadres",
                "validators": [
                    {
                        "type": "required"
                    }
                ]
            }
        },
        {
            "type": "field",
            "field": {
                "type": "radio",
                "name": "cms_type",
                "label": "Type aanvraag",
                "options": {
                    "particulier": "Particulier",
                    "zakelijk": "Zakelijk"
                }
            }
        },
        {
            "type": "field",
            "field": {
                "type": "text",
                "name": "cms_bedrijf",
                "label": "Bedrijfsnaam",
                "hint": "Zoals ingeschreven bij de KvK",
                "validators": [
                    {
                        "type": "required"
                    }
                ],
                "conditional": {
                    "field": "cms_type",
                    "operator": "equal",
                    "value": "zakelijk"
                }
            }
        },
        {
            "type": "field",
            "field": {
                "type": "select",
                "name": "cms_land",
                "label": "Land",
                "options": {
                    "nl": "Nederland",
                    "be": "België",
                    "de": "Duitsland"
                }
            }
        },
        {
            "type": "field",
            "field": {
                "type": "text",
                "name": "cms_btw",
                "label": "BTW-nummer",
                "placeholder": "NL123456789B01",
                "conditional": {
                    "logic": "and",
                    "rules": [
                        {
                            "field": "cms_type",
                            "operator": "equal",
                            "value": "zakelijk"
                        },
                        {
                            "field": "cms_land",
                            "operator": "notequal",
                            "value": "nl"
                        }
                    ]
                }
            }
        },
        {
            "type": "field",
            "field": {
                "type": "textarea",
                "name": "cms_bericht",
                "label": "Uw vraag of opmerking",
                "placeholder": "Beschrijf uw wens...",
                "rows": 4,
                "validators": [
                    {
                        "type": "required"
                    },
                    {
                        "type": "minLength",
                        "min": 10
                    }
                ]
            }
        },
        {
            "type": "field",
            "field": {
                "type": "checkbox",
                "name": "cms_akkoord",
                "checkboxLabel": "Ik ga akkoord met de privacyverklaring",
                "validators": [
                    {
                        "type": "required"
                    }
                ]
            }
        }
    ]
}