Milk Admin

FormBuilder - Action Management

FormBuilder actions allow you to manage form buttons (save, delete, cancel, etc.) with advanced features such as custom callbacks, conditional visibility, and validation.

Method Reference Summary

Method Description
addStandardActions(bool $include_delete = false, ?string $cancel_link = null) Adds pre-configured Save/Delete/Cancel buttons. Quick helper for common form actions.
setActions(array $actions) Replaces all existing actions with new ones. Use when you want complete control over buttons.
addActions(array $actions) Adds actions without replacing existing ones. Useful for adding custom buttons after addStandardActions().
getPressedAction() Returns the action key that triggered the submit (e.g., save, cancel, custom).
setMessageSuccess(string $message) Customizes the success message shown after successful save operation. Default: "Save successful"
setMessageError(string $message) Customizes the error message shown when save fails. Default: "Save failed"

Basic Usage

The simplest way to add buttons to the form is to use addStandardActions():

$form = FormBuilder::create($model, $this->page)
    ->field('title')->label('Title')->required()
    ->field('content')->formType('textarea')
    ->addStandardActions(false, '?page=posts')  // Only Save and Cancel
    ->getForm();

To include the Delete button as well:

->addStandardActions(true, '?page=posts')  // Save, Delete and Cancel

Action Parameters

Parameter Type Default Description
label string Capitalized key Button text
type string 'submit' 'submit', 'button' or 'link'
class string 'btn btn-primary' CSS classes for styling
action callable - Callback function: function($fb, $request): array
Returns: ['success' => bool, 'message' => string]
link string - URL for link-type buttons
validate bool true Enable/disable HTML5 validation
confirm string - Confirmation message before submit
onclick string - Custom JavaScript onclick handler
target string - Link target: _blank, _self, etc.
attributes array [] Custom HTML attributes as key=>value pairs (e.g., ['data-id' => '123', 'title' => 'Click me'])
showIf array - Conditional visibility: [$field, $operator, $value]

showIf Operators

Operator Description Example
'empty' Field is empty, null, 0 or empty string ['status', 'empty', 0]
'not_empty' Field has a value ['id', 'not_empty', 0]
'=' or '==' Equal to value ['status', '=', 'draft']
'!=' or '<>' Not equal to value ['status', '!=', 'published']
'>', '<', '>=', '<=' Comparison operators ['price', '>', 100]

Static Helpers

Helper Description
\Builders\FormBuilder::saveAction() Standard save operation with redirect
\Builders\FormBuilder::deleteAction($url_success, $url_error) Delete operation with custom redirect URLs

Examples by Action Type

Basic Submit Action

A submit button with standard save action:

->setActions([
    'save' => [
        'label' => 'Save',
        'class' => 'btn btn-primary',
        'action' => \Builders\FormBuilder::saveAction()
    ]
])

Action with Custom Callback

A button that executes a custom callback before or after saving:

->addActions([
    'publish' => [
        'label' => 'Publish',
        'class' => 'btn btn-success',
        'action' => function($fb, $request) {
            // Save the data
            $result = $fb->save($request);

            // If save is successful, update the status
            if ($result['success']) {
                $fb->getModel()->update(['status' => 'published']);
                $result['message'] = 'Post published successfully!';
            }

            return $result;
        }
    ]
])

Link Action

A button that works as a link (does not submit):

->addActions([
    'cancel' => [
        'label' => 'Cancel',
        'type' => 'link',
        'class' => 'btn btn-secondary',
        'link' => '?page=posts'
    ],
    'preview' => [
        'label' => 'Preview',
        'type' => 'link',
        'class' => 'btn btn-outline-primary',
        'link' => '?page=posts&action=view&id=' . $id,
        'target' => '_blank'
    ]
])

Action with Confirmation

Button that requires confirmation before execution:

->addActions([
    'delete' => [
        'label' => 'Delete',
        'class' => 'btn btn-danger',
        'action' => \Builders\FormBuilder::deleteAction(),
        'validate' => false,
        'confirm' => 'Are you sure you want to delete this item?'
    ]
])

Action with Conditional Visibility

Buttons that appear only when specific conditions are met:

->addActions([
    'delete' => [
        'label' => 'Delete',
        'class' => 'btn btn-danger',
        'action' => \Builders\FormBuilder::deleteAction(),
        'showIf' => ['id', 'not_empty', 0]  // Show only if ID exists
    ],
    'publish' => [
        'label' => 'Publish',
        'class' => 'btn btn-success',
        'action' => function($fb, $request) { /* ... */ },
        'showIf' => ['status', '=', 'draft']  // Show only if status is draft
    ],
    'archive' => [
        'label' => 'Archive',
        'class' => 'btn btn-warning',
        'action' => function($fb, $request) { /* ... */ },
        'showIf' => ['status', '=', 'published']  // Show only if published
    ]
])

Action with Custom Attributes

Buttons with custom HTML attributes for custom JavaScript:

->addActions([
    'export' => [
        'label' => 'Export',
        'type' => 'button',
        'class' => 'btn btn-info',
        'onclick' => 'exportData()',
        'attributes' => [
            'data-action' => 'export',
            'data-format' => 'csv',
            'data-id' => $model->id,
            'title' => 'Export to CSV'
        ]
    ]
])

Difference between setActions() and addActions()

  • setActions(): Completely replaces all existing actions. Useful when you want total control over the buttons.
  • addActions(): Adds new actions to existing ones. Useful for adding custom buttons after using addStandardActions().
// Use addStandardActions for base buttons
->addStandardActions(true, '?page=posts')

// Then add custom buttons with addActions
->addActions([
    'publish' => [
        'label' => 'Publish',
        'class' => 'btn btn-success',
        'action' => function($fb, $request) { /* ... */ },
        'showIf' => ['status', '=', 'draft']
    ]
])

Customizing Success and Error Messages

You can customize the messages displayed when a save operation succeeds or fails using setMessageSuccess() and setMessageError():

$form = FormBuilder::create($model, $this->page)
    ->field('title')->label('Title')->required()
    ->field('content')->formType('textarea')
    ->setMessageSuccess('Lesson saved successfully!')
    ->setMessageError('Unable to save the lesson. Please try again.')
    ->addStandardActions(false, '?page=lessons')
    ->getForm();

These messages work both with:

  • JSON mode (only_json = true): The message is returned in the JSON response
  • Redirect mode: The message is shown as a flash message after redirect

This is particularly useful when you want domain-specific messages instead of generic "Save successful" or "Save failed".

Complete Example

namespace Modules\Posts;

use App\Abstracts\AbstractController;
use App\{Response, Route};
use Builders\FormBuilder;

class PostsController extends AbstractController
{
    public function edit() {
        $response = $this->getCommonData();

        $response['form'] = FormBuilder::create($this->model, $this->page)
            // Field configuration
            ->field('title')
                ->label('Post Title')
                ->required()

            ->field('content')
                ->formType('editor')
                ->label('Content')
                ->required()

            ->field('status')
                ->formType('select')
                ->options([
                    'draft' => 'Draft',
                    'published' => 'Published',
                    'archived' => 'Archived'
                ])
                ->value('draft')

            // Standard buttons
            ->addStandardActions(true, '?page=posts')

            // Additional custom buttons
            ->addActions([
                // Publish button - visible only for draft
                'publish' => [
                    'label' => 'Publish',
                    'class' => 'btn btn-success',
                    'action' => function($fb, $request) {
                        $result = $fb->save($request);
                        if ($result['success']) {
                            $fb->getModel()->update(['status' => 'published']);
                            $result['message'] = 'Post published successfully!';
                        }
                        return $result;
                    },
                    'showIf' => ['status', '=', 'draft']
                ],

                // Archive button - visible only for published
                'archive' => [
                    'label' => 'Archive',
                    'class' => 'btn btn-warning',
                    'action' => function($fb, $request) {
                        $result = $fb->save($request);
                        if ($result['success']) {
                            $fb->getModel()->update(['status' => 'archived']);
                        }
                        return $result;
                    },
                    'confirm' => 'Archive this post?',
                    'showIf' => ['status', '=', 'published']
                ],

                // Preview link in new window
                'preview' => [
                    'label' => 'Preview',
                    'type' => 'link',
                    'class' => 'btn btn-outline-primary',
                    'link' => '?page=posts&action=view&id=' . ($this->model->id ?? ''),
                    'target' => '_blank',
                    'showIf' => ['id', 'not_empty', 0]
                ]
            ])

            ->getForm();

        $response['title'] = 'Edit Post';
        Response::render(__DIR__ . '/Views/edit_page.php', $response);
    }
}
Loading...