Form Containers with FormBuilder
This guide shows how to organize form fields using Bootstrap grid layouts with the addContainer() method in FormBuilder. Containers allow you to create professional, responsive multi-column layouts for better form organization.
addContainer() method is implemented in FormContainerManagementTrait and automatically integrated into FormBuilder.
Container Overview
The addContainer() method provides:
- Bootstrap Grid Layout: Uses Bootstrap's responsive
col-md-Xclasses - Equal or Custom Columns: Specify number of columns or custom column sizes
- Automatic Wrapping: Extra fields automatically wrap to new rows
- Custom Styling: Add class, style, id, or any HTML attributes
- Positioning Control: Insert before specific fields or append at the end
- Optional Titles: Add descriptive titles to each container
Method Signature
public function addContainer(
string $id, // Unique container ID
array $fields, // Array of field names to include
int|array $cols, // Number of columns OR array of column sizes
string $position_before, // Field name before which to insert (empty = append)
string $title, // Optional container title
array $attributes // Additional HTML attributes (class, style, etc.)
): self
Basic Usage
Example 1: Equal Columns
Create a container with 3 equal columns:
$form = \Builders\FormBuilder::create($this->model, $this->page)
// Add 3 fields in 3 equal columns (col-md-4 each)
->addContainer(
'contact_info', // Container ID
['name', 'email', 'phone'], // Fields to include
3, // 3 equal columns
'status', // Insert before 'status' field
'Contact Information', // Container title
['class' => 'border rounded p-3 mb-4'] // Custom styling
)
->addStandardActions()
->render();
Example 2: Custom Column Sizes
Create a container with custom column sizes using Bootstrap grid (total 12):
$form = \Builders\FormBuilder::create($this->model, $this->page)
// Custom column sizes: [4, 5, 3] = col-md-4, col-md-5, col-md-3
->addContainer(
'address_info',
['address', 'city', 'zip_code'],
[4, 5, 3], // Custom sizes (must sum to 12)
'', // Empty = append at end
'Address Information',
['class' => 'border rounded p-3', 'style' => 'background-color: #f8f9fa;']
)
->render();
Example 3: Automatic Wrapping
When you have more fields than columns, they automatically wrap to new rows:
$form = \Builders\FormBuilder::create($this->model, $this->page)
// 5 fields in 3 columns = 2 rows (3 fields + 2 fields)
->addContainer(
'user_details',
['first_name', 'last_name', 'email', 'phone', 'birthdate'],
3, // 3 columns per row
'password',
'User Details (Auto-wrapping)',
['class' => 'border p-3 mb-4', 'style' => 'background-color: #e7f3ff;']
)
->render();
Complete Module Example
This example demonstrates a complete working module with multiple containers:
Step 1: Create the Module PHP File
Create milkadmin/Modules/TestFormContainerModule.php:
<?php
namespace Modules;
use App\Abstracts\{AbstractModule, AbstractModel};
use App\Attributes\RequestAction;
use App\Response;
class TestFormContainerModule extends AbstractModule {
protected function configure($rule): void
{
$rule->page('testFormContainer')
->title('Test Form Container')
->menu('Test Form Container')
->access('public');
}
#[RequestAction('home')]
public function home() {
$id = _absint($_REQUEST['id'] ?? 0);
$data = $this->model->getByIdForEdit($id);
$form = \Builders\FormBuilder::create($this->model, $this->page)
// Add extra fields for testing
->addField('email', 'email', ['label' => 'Email Address'])
->addField('phone', 'tel', ['label' => 'Phone Number'])
->addField('address', 'string', ['label' => 'Address'])
->addField('city', 'string', ['label' => 'City'])
->addField('zip_code', 'string', ['label' => 'ZIP Code'])
// Demo 1: Equal columns with wrapping
->addContainer('container1',
['name', 'email', 'phone', 'city', 'zip_code'],
3, // 3 equal columns
'status',
'Contact Information (3 cols, 5 fields = 2 rows)',
['class' => 'border rounded p-3 mb-4', 'style' => 'background-color: #f8f9fa;']
)
// Demo 2: Custom column sizes
->addContainer('container2',
['address', 'status', 'password'],
[4, 5, 3], // Custom sizes
'', // Append at end
'Address & Status (custom sizes: 4, 5, 3)',
['class' => 'border rounded p-3 mb-4', 'style' => 'background-color: #e7f3ff;']
)
->addStandardActions()
->render();
Response::render($form);
}
}
class TestFormContainerModel extends AbstractModel {
protected function configure($rule): void
{
$rule
->table('test_form_container')
->id()
->string('name', 100)
->string('status', 50)->options([
'pending' => 'Pending',
'active' => 'Active',
'inactive' => 'Inactive',
'archived' => 'Archived'
])->formType('list')
->string('password', 100, false);
}
}
Container Features in Detail
1. Container ID
The container ID is used as the HTML id attribute for the container div:
->addContainer('my_container', [...], 3, '', '', [])
// Generates: <div id="my_container" class="...">...</div>
2. Field Names Array
Specify which fields to include in the container. All fields must exist in the form. You can also include inline HTML snippets in the array to render custom content inside a column.
// ✓ Valid - fields exist
->addContainer('container1', ['name', 'email', 'phone'], 3, '', '', [])
// ✗ Invalid - 'nonexistent_field' doesn't exist
->addContainer('container2', ['name', 'nonexistent_field'], 2, '', '', [])
// Throws: InvalidArgumentException: Field 'nonexistent_field' does not exist in the form
3. Column Configuration
Integer (Equal Columns):
->addContainer('container1', ['field1', 'field2', 'field3'], 3, '', '', [])
// Creates: col-md-4, col-md-4, col-md-4 (12/3 = 4)
Array (Custom Sizes):
->addContainer('container2', ['field1', 'field2', 'field3'], [4, 5, 3], '', '', [])
// Creates: col-md-4, col-md-5, col-md-3 (total = 12)
4. Position Control
Control where the container appears in the form:
// Insert before 'status' field
->addContainer('container1', [...], 3, 'status', '', [])
// Append at the end (empty string or omit)
->addContainer('container2', [...], 3, '', '', [])
5. Container Title
Add a descriptive title to the container:
->addContainer('container1', [...], 3, '', 'Contact Information', [])
// Generates: <h4 class="mb-3">Contact Information</h4>
6. Custom Attributes
Add any HTML attributes to the container div:
->addContainer('container1', [...], 3, '', 'Title', [
'class' => 'border rounded p-3 mb-4',
'style' => 'background-color: #f8f9fa;',
'data-section' => 'contact',
'id' => 'custom-id' // Note: 'id' will be overridden by container ID
])
Generated HTML Structure
The addContainer() method generates a Bootstrap grid structure:
<!-- Container with 3 equal columns -->
<div class="border rounded p-3 mb-4" id="contact_info" style="background-color: #f8f9fa;">
<h4 class="mb-3">Contact Information</h4>
<!-- Row 1 (first 3 fields) -->
<div class="row g-3 milk-row-1 mb-3">
<div class="col-md-4">
<!-- name field HTML -->
</div>
<div class="col-md-4">
<!-- email field HTML -->
</div>
<div class="col-md-4">
<!-- phone field HTML -->
</div>
</div>
<!-- Row 2 (remaining fields, if wrapping) -->
<div class="row g-3 milk-row-2">
<div class="col-md-4">
<!-- additional field -->
</div>
</div>
</div>
Related Documentation
- Field Management: Adding, removing, modifying, and organizing form fields
- Conditional Field Visibility: Show/hide fields based on other field values
- Form Validation: Custom validation and error handling
- Organizing Fields in columns with Containers: Grouping fields into containers for better organization