PHPackages                             bigfork/silverstripe-formtacular - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. bigfork/silverstripe-formtacular

ActiveSilverstripe-vendormodule[Utility &amp; Helpers](/categories/utility)

bigfork/silverstripe-formtacular
================================

3.0.0(6mo ago)01.1k↓50%1BSD-3-ClausePHP

Since Feb 24Pushed 6mo ago4 watchersCompare

[ Source](https://github.com/bigfork/silverstripe-formtacular)[ Packagist](https://packagist.org/packages/bigfork/silverstripe-formtacular)[ RSS](/packages/bigfork-silverstripe-formtacular/feed)WikiDiscussions master Synced 1mo ago

READMEChangelogDependencies (1)Versions (18)Used By (1)

Silverstripe Formtacular
========================

[](#silverstripe-formtacular)

A replacement/combination of [display-logic](https://github.com/unclecheese/silverstripe-display-logic) and [zenvalidator](https://github.com/sheadawson/silverstripe-zenvalidator), without the jQuery and jQuery Entwine dependencies.

Required CSS
------------

[](#required-css)

No frontend CSS is provided for this because it's pretty simple for 99% of use-cases, and loading it from a separate CSS file seems wasteful when it's so easy to add to an existing project:

```
div.formtacular-hidden {
    display: none;
}
```

If you conditionally show/hide other elements, e.g. `HeaderField`, you may need to expand the selector list. Try to avoid using the `.formtacular-hidden` class selector alone (i.e. without an element), as this class will be added to *both* the field holder div and the form field itself by Silverstripe, so your fields may end up always invisible!

Quick example
-------------

[](#quick-example)

```
$fields = FieldList::create(
    TextField::create('FirstName', 'First name'),
    TextField::create('Surname', 'Surname'),
    TextField::create('ContactMethod', 'Contact method', [
        'Email' => 'Email',
        'Telephone' => 'Telephone'
    ]),
    $email = EmailField::create('Email', 'Email'),
    $telephone = TextField::create('Telephone', 'Telephone')
);

$email->displayIf('ContactMethod')->isEqualTo('Email');
$email->validateIfVisible();

$telephone->displayIf('ContactMethod')->isEqualTo('Telephone');
$telephone->validateIfVisible();

// This subclass of RequiredFields is currently necessary
// It may be possible in Silverstripe 5 to remove this by utilising field validation extension hooks
$validator = \Bigfork\SilverstripeFormtacular\Validators\RequiredFields::create([
    'Name',
    'Surname',
    'ContactMethod',
    'Email',
    'Telephone'
])
```

Switching from display-logic
----------------------------

[](#switching-from-display-logic)

- Add this module to your composer requirements, it’ll automatically replace `display-logic` in any dependencies or sub-dependencies that require it
- Switch from `Wrapper::create()` to just using `CompositeField::create()`. This step can be skipped as a `Wrapper`class is provided to try to make life a little easier

AJAX forms
----------

[](#ajax-forms)

Depending on how you handle AJAX forms, you may need to re-initialise the JavaScript after submission. As every approach is different, you will need to implement your own logic for re-initialising the form if/when HTML is modified. For example a popular way of handling AJAX form submissions is to replace the entire form HTML with the response from the server; so your form handler could do something like:

```
// Your import path may vary
import FormtacularForm from '~vendor/bigfork/silverstripe-formtacular/client/src/js/classes/FormtacularForm';

.then((response) => {
  const formHTML = response;
  let $form = $container.find('form');

  const forms = window['formtacular_forms'];
  forms.remove($form.get(0));

  $form.replaceWith(formHTML);
  $form = $container.find('form'); // Re-fetch to get new

  const formtacularForm = new FormtacularForm($form.get(0));
  forms.set(node, form);
});
```

An alternative “global” way of handling this is to use a `MutationObserver` to detect when any form is added to or removed from the document:

```
// Your import path may vary
import FormtacularForm from '~vendor/bigfork/silverstripe-formtacular/client/src/js/classes/FormtacularForm';

const observer = new MutationObserver((mutations) => {
  const forms = window['formtacular_forms'];

  mutations.forEach((mutation) => {
    [...mutation.removedNodes].forEach((node) => {
      if (node.nodeName === 'FORM') {
        forms.remove(node);
      }
    });

    [...mutation.addedNodes].forEach((node) => {
      if (node.nodeName === 'FORM') {
        if (!node.hasAttribute('data-formtacular-visibility')) {
          return;
        }

        const form = new FormtacularForm(node);
        forms.set(node, form);
      }
    });
  });
});

addEventListener('DOMContentLoaded', () => {
  observer.observe(document.body, { childList: true, subtree: true });
});
```

Customisation
-------------

[](#customisation)

If you need to change how field values are fetched or how events are bound, like if you’re using a JavaScript library to decorate form fields, you can do so by overriding global functions registered against `window`. For example in the CMS bundle for this module, as jQuery is available we utilise it to fetch field values:

```
window['formtacular_bindChangeEvent'] = (input, handler) => {
    $(input).on('change input', handler);
};
```

Check out the source JavaScript in `client/src/js/rules` and `client/src/js/utils` directories for a full list of functions that can be overridden and when you might wish to do so.

Adding checks/rules
-------------------

[](#adding-checksrules)

You can write your own checks by extending `Bigfork\SilverstripeFormtacular\Rules\AbstractRule`, registering it in YAML and writing an accompanying JavaScript function:

```
