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
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.
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"
}
]
}
}
]
}