laravel-form-builder icon indicating copy to clipboard operation
laravel-form-builder copied to clipboard

Add Fieldset type

Open valentinoeval opened this issue 2 years ago • 3 comments

I need to create < fieldset > element into form with associated fields list like subform

valentinoeval avatar Dec 07 '22 12:12 valentinoeval

You can do that in your view, using the global form functions like form_start, form_row, etc. See helpers.php.

There are several other issues where we decided not to create a fieldset field.

rudiedirkx avatar Dec 07 '22 18:12 rudiedirkx

Mainly #582

rudiedirkx avatar Dec 07 '22 18:12 rudiedirkx

Fieldset is a form element who deserves to have his own element. For those who would absolutely like to generate this element here is my class

  • FieldsetType.php :
<?php

namespace App\Forms\Fields;

use Kris\LaravelFormBuilder\Events\AfterFieldCreation;
use Kris\LaravelFormBuilder\Fields\FormField;
use Kris\LaravelFormBuilder\Form;

/**
 * Generate <fieldset> element to build inputs block
 *
 * @author Valentin GOLLIOT
 * @since 2022-12-08
 */
class FieldsetType extends FormField
{
    /**
     * All fields that are added.
     *
     * @var array
     */
    protected $fields = [];

    /**
     * Wether the fieldset is beign rebuild.
     *
     * @var bool
     */
    protected $rebuilding = false;

    /**
     * Form specific configuration.
     *
     * @var array
     */
    protected $fieldsetConfig = [];

    /**
     * @var string
     */
    protected $templatePrefix;

    /**
     * @var array
     */
    protected $defaultOptions = [];

    /**
     * Get template from options if provided, otherwise fallback to config.
     *
     * @return mixed
     */
    protected function getTemplate()
    {
        return $this->getTemplatePrefix() . $this->getConfig('fieldset');
    }

    /**
     * @param string $name
     * @param string $type
     * @param Form $parent
     * @param array $options
     */
    public function __construct($name, $type, Form $parent, array $options = [])
    {
        $optionsMerged = array_merge_recursive($this->defaultOptions, $options);

        parent::__construct($name, $type, $parent, $optionsMerged);
    }

    /**
     * Create a new field and add it to the form.
     *
     * @param string $name
     * @param string $type
     * @param array  $options
     * @param bool   $modify
     * @return $this
     */
    public function add($name, $type = 'text', array $options = [], $modify = false)
    {
        $this->formHelper->checkFieldName($name, get_class($this));

        if ($this->rebuilding && !$this->has($name)) {
            return $this;
        }

        $this->addField($this->makeField($name, $type, $options), $modify);

        return $this;
    }

    /**
     * Check if fieldset has field.
     *
     * @param string $name
     * @return bool
     */
    public function has($name)
    {
        return array_key_exists($name, $this->fields);
    }

    /**
     * Render the fieldset.
     *
     * @param array $options
     * @param bool  $showLabel
     * @param bool  $showField
     * @param bool  $showError
     * @return string
     */
    public function render(array $options = [], $showLabel = true, $showField = true, $showError = true)
    {
        $fieldsetTitle = (isset($this->options['title'])) ? $this->options['title'] : '';

        return $this->formHelper->getView()
            ->make($this->getTemplate())
            ->with('fields', $this->fields)
            ->with('fieldsetTitle', $fieldsetTitle)
            ->with('fieldsetName', $this->options['label'])
            ->render();
    }

    /**
     * Get template prefix that is prepended to all template paths.
     *
     * @return string
     */
    public function getTemplatePrefix()
    {
        return $this->getConfig('template_prefix');
    }

    /**
     * Get the passed config key using the custom
     * fieldset config, if any.
     *
     * @param string $key
     * @param mixed $default
     *
     * @return mixed
     */
    public function getConfig($key = null, $default = null)
    {
        return $this->formHelper->getConfig($key, $default, $this->fieldsetConfig);
    }

    /**
     * Add a FormField to the form's fields.
     *
     * @param FormField $field
     * @return $this
     */
    protected function addField(FormField $field, $modify = false)
    {
        $this->fields[$field->getRealName()] = $field;

        return $this;
    }

    /**
     * Create the FormField object.
     *
     * @param string $name
     * @param string $type
     * @param array  $options
     * @return FormField
     */
    protected function makeField($name, $type = 'text', array $options = [])
    {
        $this->setupFieldOptions($name, $options);

        $fieldName = $this->getFieldName($name);
        $fieldType = $this->getFieldType($type);

        return new $fieldType($fieldName, $type, $this->parent, $options);
    }

    /**
     * Set up options on single field depending on form options.
     *
     * @param string $name
     * @param $options
     */
    protected function setupFieldOptions($name, &$options)
    {
        $options['real_name'] = $name;
    }

    /**
     * If form is named form, modify names to be contained in single key (parent[child_field_name]).
     *
     * @param string $name
     * @return string
     */
    protected function getFieldName($name)
    {
        $formName = $this->getName();
        if ($formName !== null) {
            if (strpos($formName, '[') !== false || strpos($formName, ']') !== false) {
                return $this->formHelper->transformToBracketSyntax(
                    $this->formHelper->transformToDotSyntax(
                        $formName . '[' . $name . ']'
                    )
                );
            }

            return $formName . '[' . $name . ']';
        }

        return $name;
    }

    /**
     * Returns and checks the type of the field.
     *
     * @param string $type
     * @return string
     */
    protected function getFieldType($type)
    {
        $fieldType = $this->formHelper->getFieldType($type);

        return $fieldType;
    }
}
  • config/laravel-form-builder.php :
...
'fieldset'      => 'laravel-form-builder::fieldset',
'custom_fields' => [
    'fieldset' => \App\Forms\Fields\FieldsetType::class,
],
...
  • resources/views/vendor/laravel-form-builder/fieldset.php :
<div class="col-3">
    <div class="card shadow">
        <?php if ($fieldsetTitle) : ?>
            <div class="card-header">
                <h5 class="card-title">
                    <?php echo __($fieldsetTitle) ?>
                    <i class="fa fa-chevron-up chervron-margin show-hide-card"
                       data-bs-toggle="collapse"
                       data-bs-target="#fieldset-<?php echo $fieldsetName ?>"
                       aria-expanded="true"
                       aria-controls="#fieldset-<?php echo $fieldsetName ?>"
                    ></i>
                </h5>
            </div>
        <?php endif; ?>
        <div id="fieldset-<?php echo $fieldsetName ?>" class="card-body collapse show">
            <?php foreach ($fields as $field): ?>
                <?php echo $field->render() ?>
            <?php endforeach; ?>
        </div>
    </div>
</div>

valentinoeval avatar Dec 09 '22 14:12 valentinoeval