Milk Admin

FormBuilder Class Documentation

The FormBuilder class provides a fluent interface for creating and managing dynamic forms, simplifying form generation and handling compared to using ObjectToForm directly.

System Overview

FormBuilder acts as a wrapper that combines:

  • ObjectToForm: Form field generation and HTML creation
  • Model Integration: Data validation and save/delete operations
  • Action System: Configurable form buttons and callbacks
  • CSRF Protection: Automatic token handling

It provides a single, chainable API for building forms with less code and better readability.

Method Reference Summary

Category Method Description
Form Setup create($model, $page = '', $url_success = null, $url_error = null) Factory method to create FormBuilder instance (static)
page(string $page) Set the page identifier
currentAction(string $action) Set form context (edit/create)
formAttributes(array $attributes) Set form HTML attributes
setId(string $formId) Set form ID attribute
urlSuccess(string $url) Set success redirect URL
urlError(string $url) Set error redirect URL
customData(string $key, $value) Add custom hidden field data to the form
Field Management addFieldsFromObject(object $obj, string $action) Add fields from data object
addField(string $name, array $config) Add individual field
addRelatedField(string $field) Add field from hasOne related table (e.g., 'badge.badge_number')
removeField(string $name) Remove field
fieldOrder(array $order) Set field display order
addHtml(string $key, string $html) Add custom HTML content
Actions setActions(array $actions) Replace all existing actions
addActions(array $actions) Add actions without replacing existing ones
addStandardActions(bool $include_delete = false, ?string $cancel_link = null) Add pre-configured save/delete/cancel actions
getPressedAction() Return the action key that triggered the submit (save, cancel, custom)
setMessageSuccess(string $message) Customize success message (default: "Save successful")
setMessageError(string $message) Customize error message (default: "Save failed")
saveAction() / deleteAction() Static helper methods for standard actions
Response Types asOffcanvas() Set response type to offcanvas
asModal() Set response type to modal
asDom(string $id) Set response type to DOM element
setTitle(string $new, ?string $edit = null) Set titles for new and edit modes
size(string $size) Set size for modal/offcanvas ('sm', 'lg', 'xl', 'fullscreen')
Operations save(array $request) Save form data with validation
delete(array $request, ?string $url_success, ?string $url_error) Delete record
getModel() Get model instance
Output getForm() Get form HTML
getResponse() Get response array for offcanvas/modal/dom
render() Render form HTML (alias for getForm)

Basic Usage

Constructor and Factory Method

// Factory method (recommended)
$form = \Builders\FormBuilder::create($model, $page = '', $url_success = '', $url_error = ''); 

Simple Form Creation


$form = \Builders\FormBuilder::create($model)
    ->getForm();

echo $form;
    

Field Management

FormBuilder provides flexible methods to manage form fields. For detailed information on adding, removing, modifying, and organizing fields, see the dedicated guide:

📘 Field Management Guide

→ FormBuilder - Field Management
Learn how to add fields automatically from Models, add custom fields manually, remove/modify fields, set field order, and more.

Working with Related Tables (hasOne)

FormBuilder supports editing fields from related tables using the hasOne relationship. For detailed documentation on using addRelatedField(), see the Field Management guide:

📘 Related Fields Documentation

→ FormBuilder - Field Management: Working with Related Tables
Learn how to add fields from hasOne related tables, including examples with EmployeeBadge.

Quick Overview

$form = \Builders\FormBuilder::create($this->model, 'posts', '?page=posts')

    // Remove unwanted fields
    ->removeField('created_at')
    ->removeField('updated_at')

    // Modify existing fields
    ->modify_field('title', ['label' => 'Post Title'])

    // Add custom fields
    ->addField('custom_field', ['label' => 'Custom', 'form-type' => 'string'])

    // Set field order
    ->fieldOrder(['id', 'title', 'content', 'status'])

    ->render();
    

Actions Configuration

FormBuilder provides a flexible action system for managing form buttons (save, delete, custom actions, etc.). For comprehensive documentation on actions, see the dedicated guide:

📘 Action Management Guide

→ FormBuilder - Action Management
Learn how to create standard buttons, custom actions, link buttons, and conditional visibility with showIf.

Quick Overview

// Standard actions (recommended for CRUD)
$form = \Builders\FormBuilder::create($this->model,'posts', '?page=posts')
    ->addStandardActions(true, '?page=posts') // save, delete, cancel
    ->getForm();

// Custom actions
$form = \Builders\FormBuilder::create($this->model,'posts', '?page=posts')
    ->setDefaultActions()
    ->getForm();
    

Custom Action Callbacks

Creating Custom Callbacks


class PostModule extends AbstractModule {
    
    public function actionEdit() {
        $data_object = $this->model->getByIdForEdit($id);
        
        $form_builder = FormBuilder::create($this->model, $this->page, '?page='.$this->page)
            ->setActions([
                'save_and_continue' => [
                    'label' => 'Save & Continue',
                    'class' => 'btn btn-success',
                    'action' => [$this, 'saveAndContinueCallback']
                ],
                'publish' => [
                    'label' => 'Publish',
                    'class' => 'btn btn-primary',
                    'action' => [$this, 'publishCallback']
                ]
            ]);
        
        $form_html = $form_builder->getForm();
        // Handle form output...
    }
    
    // Custom callback - receives FormBuilder instance and request data
    public function saveAndContinueCallback($form_builder, $request) {
        // Use FormBuilder's built-in save method
        $result = $form_builder->store($request, null, null);
        
        if ($result['success']) {
            // Custom redirect logic
            $model = $form_builder->getModel();
            $id = $request[$model->getPrimaryKey()] ?? 0;
            Route::redirectSuccess('?page='.$this->page.'&action=edit&id='.$id, 'Saved successfully');
        }
        
        return $result;
    }
    
    public function publishCallback($form_builder, $request) {
        // Custom business logic
        $request['status'] = 'published';
        $request['published_at'] = date('Y-m-d H:i:s');
        
        // Save with FormBuilder
        $result = $form_builder->store($request, '?page='.$this->page);
        
        if ($result['success']) {
            MessagesHandler::addSuccess('Post published successfully');
        }
        
        return $result;
    }
}
    

Built-in Methods

Save Method


// FormBuilder provides a built-in save method that handles:
// - Data validation using model
// - Automatic updated_at timestamp
// - Success/error handling
// - Redirects

$result = $form_builder->store($request, $redirect_success, $redirect_error);
// Returns: ['success' => true/false, 'message' => '...', 'data' => [...]]

// Usage in callback
public function customSaveCallback($form_builder, $request) {
    // Modify data before saving
    $request['custom_field'] = 'custom_value';
    
    // Use FormBuilder's save method
    $form_builder->validate($request);
    return $form_builder->store($request, '?page=success', '?page=error');
}
    

Delete Method


// Built-in delete method
$result = $form_builder->delete($id, $redirect_success, $redirect_error);

// Usage in callback
public function customDeleteCallback($form_builder, $request) {
    $id = $request['id'] ?? 0;
    
    // Custom pre-delete logic
    $this->cleanup_related_data($id);
    
    // Use FormBuilder's delete method
    return $form_builder->delete($id, '?page=list', '?page=error');
}
    

Form Output and Integration

Getting Form HTML


$form_builder = FormBuilder::create($this->model,'posts', '?page=posts')
    ->setActions([...]);

// Get form HTML
$form_html = $form_builder->getForm();

// Get any action results (from POST processing)
$action_results = $form_builder->getFunctionResults();

// Prepare response data
$response = [
    'id' => $id,
    'form' => $form_html,
    'page' => $this->page
];

// Render with Response
Response::render(__DIR__ . '/views/edit_page.php', $response);
    

Module Integration


// Before FormBuilder (verbose approach)
public function actionEdit() {
    $id = _absint($_REQUEST['id'] ?? 0);
    $data_object = $this->model->getByIdForEdit($id, Route::getSessionData());
    
    $object_to_form = new ObjectToForm($this->page, '?page='.$this->page, '');
    $object_to_form->current_action = 'edit';
    $form_html = $object_to_form->getForm($data_object, 'edit');
    
    Response::render(__DIR__ . '/views/edit_page.php', ['form' => $form_html]);
}

// After FormBuilder (simplified approach)
public function actionEdit() {
    $data_object = $this->model->getByIdForEdit(_absint($_REQUEST['id'] ?? 0), Route::getSessionData());
    
    $form_builder = FormBuilder::create($this->model,'posts', '?page='.$this->page)
        ->currentAction('edit')
        ->setActions([
            'save' => ['label' => 'Save', 'class' => 'btn btn-primary', 'action' => FormBuilder::saveAction('?page='.$this->page)],
            'delete' => ['label' => 'Delete', 'class' => 'btn btn-danger', 'action' => FormBuilder::deleteAction('?page='.$this->page), 'confirm' => 'Are you sure?']
        ]);

    $form_html = $form_builder->getForm();
    $action_results = $form_builder->getFunctionResults();

    $response = ['form' => $form_html, 'page' => $this->page];
    Response::render(__DIR__ . '/views/edit_page.php', $response);
}
    
📘 Complete Examples

For real-world examples including blog post forms, user registration, and multi-step forms, see the dedicated examples page (coming soon).

Next Steps

Now that you understand FormBuilder basics, explore these related topics:

Loading...