Skip to content

Instantly share code, notes, and snippets.

@jenswittmann
Created April 28, 2026 12:33
Show Gist options
  • Select an option

  • Save jenswittmann/49a6a322cb085e3d4e594392f3ff754d to your computer and use it in GitHub Desktop.

Select an option

Save jenswittmann/49a6a322cb085e3d4e594392f3ff754d to your computer and use it in GitHub Desktop.
A form builder that's simple to use, with fieldsets in a single file and Fenom syntax for MODX.
{var $forms = [
'Schule' => [
'fields' => [
'Adresse' => [
'schule' => [
'type' => 'text',
'label' => 'Schule',
'required' => true,
],
'strasse' => [
'type' => 'text',
'label' => 'Straße und Hausnummer',
'required' => true,
],
'plz' => [
'type' => 'text',
'label' => 'PLZ',
'width' => 30,
'required' => true,
],
'ort' => [
'type' => 'text',
'label' => 'Ort',
'width' => 60,
'required' => true,
],
],
'Ansprechperson' => [
'vorname' => [
'type' => 'text',
'label' => 'Vorname',
'width' => 40,
'required' => true,
],
'nachname' => [
'type' => 'text',
'label' => 'Nachname',
'width' => 50,
'required' => true,
],
'email' => [
'type' => 'text',
'label' => 'E-Mail',
'required' => true,
'validate' => ':email'
],
'telefon' => [
'type' => 'text',
'label' => 'Telefon',
],
],
'Nachricht an uns' => [
'betreff' => [
'type' => 'text',
'label' => 'Betreff',
'required' => true,
],
'nachricht' => [
'type' => 'textarea',
'label' => 'Nachricht',
'required' => true,
],
]
],
],
]}
{var $formKey = $.get.form ?: 'Schule'}
{var $fieldsValidate = []}
{var $emailTplFields = []}
{foreach $forms[$formKey]['fields'] as $title => $section}
{foreach $section as $id => $field}
{if $field['required']}
{var $fieldsValidate[] = $id ~ ( $field['validate'] ?: '' ) ~ ':required'}
{/if}
{var $emailTplFields[] = '<li><strong>' ~ $field['label'] ~ ':</strong> ' ~ $.post[$id] ~ '</li>'}
{/foreach}
{/foreach}
{var $emailTplFields = $emailTplFields | join : ''}
{'!formit' | snippet : [
'hooks' => 'FormItSaveForm,email',
'formName' => $formKey,
'formEncrypt' => true,
'emailFrom' => $_modx->config.emailsender,
'emailTo' => $fieldContent.settings.recipient,
'emailSubject' => 'Anfrage von Webseite: ' ~ $formKey,
'emailTpl' => '@CODE:
<h2>Neue Anfrage: ' ~ $formKey ~ '</h2>
<ul>
' ~ $emailTplFields ~ '
</ul>
',
'placeholderPrefix' => '',
'clearFieldsOnSuccess' => true,
'validate' => $fieldsValidate | join : ',',
'validationErrorMessage' => 'Bitte füllen Sie die erforderlichen Felder aus.',
'successMessage' => $fieldContent.settings.successMessage,
]}
<div class="col-full start-2-m end-8-m">
<h2 id="form" class="f5 b mt4 mb3">Kontaktformular</h2>
<ul class="list flex g1 f0 mb5">
{foreach $forms as $id => $form}
<li>
<a
href="{$_modx->makeUrl($_modx->resource.id)}?form={$id}#form"
class="
btn btn--rounded
{if $id == $formKey}
btn--active
{/if}
"
>{$id}</a>
</li>
{/foreach}
</ul>
<form
action="{$.server.REQUEST_URI}#form"
method="post"
class="form"
novalidate
>
{if $_modx->getPlaceholder('error_message') || $_modx->getPlaceholder('validation_error_message') || $_modx->getPlaceholder('success')}
<div
aria-live="assertive"
role="status"
class="
form__message b p4 mb5 br3 br--bl0
{if $_modx->getPlaceholder('success')}
bg-green-5
{else}
bg-red-5
{/if}
"
>
{$_modx->getPlaceholder('validation_error_message')}
{$_modx->getPlaceholder('error_message')}
{$_modx->getPlaceholder('fi.successMessage')}
</div>
{/if}
{foreach $forms[$formKey]['fields'] as $title => $section}
<fieldset class="flex flex-wrap justify-between g2 mb4 mb5-m bn">
<legend class="w-100 f4 b mt4 mt5-m mb3-m">{$title}</legend>
{foreach $section as $id => $field}
<div class="form__item w-{$field['width'] ?: '100'}">
{var $error = $_modx->getPlaceholder('error.' ~ $id)}
{if $field['type'] == 'text'}
<label for="{$id}" class="form__label f2">
{$field['label']}
{if !$field['required']}
<span class="o-50">(optional)</span>
{/if}
{if $error}
<div id="{$id}_error" class="f2 b red-5">{$error}</div>
{/if}
</label>
<div class="form__field form__field--input">
<input
type="text"
name="{$id}"
id="{$id}"
value="{$.post[$id]}"
{if $field['required']}
required
{/if}
{if $error}
aria-invalid="true"
aria-errormessage="{$id}_error"
{/if}
/>
</div>
{/if}
{if $field['type'] == 'textarea'}
<label for="{$id}" class="form__label">
{$field['label']}
{if !$field['required']}
<span class="o-50">(optional)</span>
{/if}
{if $error}
<div id="{$id}_error" class="f2 b red-5">{$error}</div>
{/if}
</label>
<div class="form__field form__field--textarea">
<textarea
name="{$id}"
id="{$id}"
{if $field['required']}
required
{/if}
{if $error}
aria-invalid="true"
aria-errormessage="{$id}_error"
{/if}
>{$.post[$id]}</textarea>
</div>
{/if}
</div>
{/foreach}
</fieldset>
{/foreach}
<p class="f2 mv4-m sa11y-ignore">
Wir schützen die übermittelten Daten. Alle Infos dazu in der <a href="{$_modx->makeUrl(23)}" target="_blank" class="bb">Datenschutzerklärung</a>.
</p>
<button
type="submit"
class="btn btn--clean btn--bubble btn--bubble-black"
>
<span>Senden</span>
<span class="icon icon-font">
{'arrow-right' | svg}
</span>
</button>
</form>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment