laravel-form-builder
laravel-form-builder copied to clipboard
Add Fieldset type
I need to create < fieldset > element into form with associated fields list like subform
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.
Mainly #582
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>