Skip to content

Latest commit

 

History

History
240 lines (190 loc) · 7.49 KB

Form.md

File metadata and controls

240 lines (190 loc) · 7.49 KB

Haste Form

About

Haste Form has been designed to ease working with Contao forms in the front end.

Examples

A lot of the following examples can be combined. For more internal details please read the source ;-)

Preparing a form instance

<?php

    // First param is the form id
    // Second is either GET or POST
    // Third is a callable that decides when your form is submitted
    // You can pass an optional fourth parameter (true by default) to turn the form into a table based one
    $objForm = new \Haste\Form\Form('someid', 'POST', function($objHaste) {
        return \Input::post('FORM_SUBMIT') === $objHaste->getFormId();
    });

    // Haste will never decide for you when the form has been submitted.
    // You have to tell it! Let's have a look at an example using GET
    // Haste will turn into the submitted state as soon as the GET param
    // "foo" contains the value "bar"
    $objForm = new \Haste\Form\Form('someid', 'GET', function() {
        return \Input::get('foo') === 'bar';
    });

    // You can optionally preserve the current GET parameters.
    // They will be added as hidden fields to the current form.
    // This is especially useful when using multiple GET forms (like search and filter).
    $objForm->preserveGetParameters();
    $objForm->preserveGetParameters(array('page_n')); // Exclude 'page_n' parameter

    // A form needs an action. By default it's the current request URI you
    // place your Haste form on, but you can either set your own URI:
    $objForm->setFormActionFromUri('https://foo.bar/somewhere.html');

    // Or you can pass a page ID that Haste will turn into an URI for your
    // convenience:
    $objForm->setFormActionFromPageId(42);

    // Now let's add form fields:
    $objForm->addFormField('year', array(
        'label'         => 'Year',
        'inputType'     => 'text',
        'eval'          => array('mandatory'=>true, 'rgxp'=>'digit')
    ));

    // Need a checkbox?
    $objForm->addFormField('termsOfUse', array(
        'label'         => array('This is the <legend>', 'This is the <label>'),
        'inputType'     => 'checkbox',
        'eval'          => array('mandatory'=>true)
    ));

    // Let's add  a submit button
    $objForm->addFormField('submit', array(
      'label'     => 'Submit form',
      'inputType' => 'submit'
    ));

    // Automatically add the FORM_SUBMIT and REQUEST_TOKEN hidden fields.
    // DO NOT use this method with generate() as the "form" template provides those fields by default.
    $objForm->addContaoHiddenFields();

    // For the ease of use we do provide two helpers for the submit button and captcha field
    $objForm->addSubmitFormField('submit', 'Submit form');
    $objForm->addCaptchaFormField('captcha');

Generating the form

Now that you have your form instance ready, you can generate the markup for it and validate the user inputs etc.

<?php

    // validate() also checks whether the form has been submitted
    if ($objForm->validate()) {

        // Get the submitted and parsed data of a field (only works with POST):
        $arrData = $objForm->fetch('year');

        // Get all the submitted and parsed data (only works with POST):
        $arrData = $objForm->fetchAll();

        // For your convenience you can also use a callable to walk over all widgets
        $arrData = $objForm->fetchAll(function($strName, $objWidget) {
            return \Input::postRaw($strName);
        });

        // Read from POST: \Input::post('year');
        // Read from GET: \Input::get('year');
    }

    // Get the form as string
    echo $objForm->generate();
    // or just
    echo $objForm;

    // You can also pass your own Template instance
    $objMyTemplate = new \FrontendTemplate('mytemplate');
    $objForm->addToTemplate($objMyTemplate);
    echo $objMyTemplate->parse();

    // Alternatively, you can pass it to any other object
    $objFilter = new \stdClass();
    $objForm->addToObject($objFilter);
    $this->Template->filter = $objFilter;

Add the form fields from a back end DCA

<?php
    // you can exclude or modify certain fields by passing a callable as second
    // parameter
    $objForm->addFieldsFromDca('tl_content', function(&$strField, &$arrDca) {

        // make sure to skip elements without inputType or you will get an exception
        if (!isset($arrDca['inputType'])) {
            return false;
        }

        // add anything you like
        if ($strField == 'myField') {
            $arrDca['eval']['mandatory'] = true;
        }

        // you must return true otherwise the field will be skipped
        return true;
    });

    // By default you can use the built-in callback that will skip fields without specified inputType
    // which normally would lead to the exception
    $objForm->addFieldsFromDca('tl_content', array($objForm, 'skipFieldsWithoutInputType'));

Add the form fields from a form generator form ID

<?php
    // you can exclude or modify certain fields by passing a callable as second
    // parameter
    $objForm->addFieldsFromFormGenerator(42, function(&$strField, &$arrDca) {
        // add anything you like
        if ($strField == 'myField') {
            $arrDca['eval']['mandatory'] = true;
        }

        // you must return true otherwise the field will be skipped
        return true;
    });

Add form fields at specific positions

By passing an \Haste\Util\ArrayPosition instance as the third parameter you can insert the field at a certain position. Available positions are:

ArrayPosition::FIRST
ArrayPosition::LAST
ArrayPosition::BEFORE
ArrayPosition::AFTER

FIRST and LAST do not require the second parameter of the constructor.

<?php
    // this example adds an explanation form field before the existing submit 
    // form field
    $objForm->addFormField('mandatory', array(
        'inputType' => 'explanation',
        'eval' => array('text' => '<p>Mandatory</p>', 'class' => 'mandatory-label')
    ), new \Haste\Util\ArrayPosition(\Haste\Util\ArrayPosition::BEFORE, 'submit'));

Removing fields on a form instance

<?php
    $objForm->removeFormField('firstname');

Bind models to the form

You can easily bind a Contao Model instance to the form to ease working with them. Haste form will try to load and preset the data from the model if there is already some and will also store the values to the model. However, it will not call ->save() on the model so you can still do with it whatever you like.

<?php
    // Presets values from page ID 42
    $objModel = \PageModel::findByPk(42);
    $objForm->bindModel($objModel);

    $objForm->addFieldsFromDca('tl_page');

    if ($objForm->validate()) {
        // The model will now contain the changes so you can save it
        $objModel->save();
    }

Add field validation

You can add your own field validation per addValidator or directly in your field using save_callback.

<?php
    // use addValidator
    $objForm->addValidator('email', function($varValue, \Widget $objWidget, Form $objForm){
        if ($varValue !== '[email protected]') {
            throw new \Exception('Wrong email address!');
        }
    
        return $varValue;
    });
    
    // or directly in your field
    $objForm->addFormField('email', [
        'save_callback' => [
            function($value) {
                if ($value !== '[email protected]') {
                    throw new \Exception('Wrong email address!');
                }
     
                return $value;
            }
        ]
    ]);