Milk Admin
Quick Form Creation with FormBuilder

This is a manual, artisanal system for creating form fields. If you need to create forms quickly from your Models, we recommend using the FormBuilder which can generate complete forms in minutes:

→ Getting Started - Forms with FormBuilder

Form

Form fields are formatted according to Bootstrap standards. The Form class helps to print them

The HTML

The class prints the form fields, not the structure

One column

The form class prints the input, label and error message. By default, fields are in floating style, but can be disabled.

<div class="form-group col-xl-6">
    <?php Form::input('text', 'name', 'Name', '', ['id'=>'sdf', 'floating'=>false]); ?>
</div>

Two columns

<div class="row g-2 mb-3">
    <div class="col-md">
        <?php Form::input('text', 'name', 'Name', ''); ?>
    </div>
    <div class="col-md">
        <?php Form::input('text', 'surname', 'Surname', ''); ?>
    </div>
</div>

The options

Within the functions to draw forms there is often an $options field, or in groups there are 2 fields options_fields and options_group. Options and options_fields are the same thing and allow you to add attributes to the field being drawn.
Some attributes are:

['class' => 'my-class', 'id' => 'my-id', 'required' => true, 'invalid-feedback'=>'The field is required','minlength' => 3, 'maxlength' => 10, 'pattern' => '[A-Za-z]{3,10}', 'placeholder' => 'Enter your name', 'size' => 10, 'step' => 2, 'min' => 0, 'max' => 10, 'multiple' => true, 'onchange' => 'alert("change")', 'oninput' => 'alert("input")']

The id, if not set, is automatically generated from the name. invalid-feedback is the error message if the field is not valid

options_group instead manages the options of checkboxes and radios groups. The settings are:

['form-check-class'=>'string', 'invalid-feedback'=>'instead of invalid_feedback of individual fields', 'form-group-class' => 'string', 'label' => 'string']

Note that placeholder doesn't work with floating enabled.


Input

Form::input($type, $name, $label, $value = '', $options = array(), $return = false)

$field = Hook:set('form_input', $field, $type, $name, $label, $value, $options)

Form::input('text', 'name', 'Name', '', ['id'=>'my-custom-id']);

Input list

Form::input('text', 'food', 'Food','', ['list'=>[
    'Pizza', 'Pasta', 'Hamburger', 'Sushi', 'Sashimi', 'Ramen', 'Soba', 'Udon', 'Tempura', 'Tonkatsu' ]]);

Input file

Form::input('file', 'file', 'File');

Upload files plugin

To handle uploads asynchronously and more comprehensively, a template plugin has been written

echo Get::themePlugin('UploadFiles',['name'=>'file', 'label'=>'File', 'value'=>'', 'options'=>[], 'upload_name' => 'my_upload1'] );

In the module I add upload handling

Hooks::set('upload_maxsize_my_upload1', function($max_size) {
    return 1024*1024*1000;
});
Hooks::set('upload_accept_my_upload1', function($accept) {
    return 'image/*';
});

In the 'upload_name' setting is the name of the upload that must be instantiated when I create the field and which allows you to set the Hooks that handle the upload

If you want to allow multiple file uploads you can add the 'multiple' => true option

Get::themePlugin('UploadFiles',['name'=>'file', 'label'=>'File', 'value'=>'', 'options'=>['multiple'=>true], 'upload_name' => 'my_upload2'] );
$max_size = Hooks::run("upload_maxsize_".$name, 10000000);
$accept = Hooks::run("upload_accept_".$name, '');
$error_msg = Hooks::run("upload_check_".$name, '', $_FILES['file']);

I send the error message. If an error message is compiled then the upload is interrupted

$temp_dir = Hooks::run('upload_save_dir_'.$name, $temp_dir);

The directory where to save the file can be changed with a hook

$file_name = Hooks::run('upload_file_name_'.$name, $file_name, $_FILES['file']);
$permission = Hooks::run('upload_permission_file_'.$name, 0666);

Files once uploaded and saved, then return the name of the uploaded file and the original name of the uploaded file

<input type="hidden" class="js-filename1" name="{input_name}_file_name[]" value="">
<input type="hidden" class="js-fileoriginalname1" name="{input_name}_file_original_name[]" value="">

Validation
The plugin handles required validation like a normal input field within bootstrap. Just set options['required'=>'true' 'invalid-feedback'=>'error message']. However, if you want to check from code whether a file has been uploaded from the upload field, since the field is always empty, the is_compiled() function is added to the field which returns boolean.
if (document.getElementById('myuploadfield').is_compiled()) { //... }


color

Form::input('color', 'color', 'Color', '#ff0000');

groups

Email @ .com
<div class="input-group">
    <span class="input-group-text">Email</span>
    <?php Form::input('Email1', '', '', '',  ['floating'=>false]); ?>
    <span class="input-group-text">@</span>
    <?php Form::select('Email2', '', ['gmail' => 'gmail', 'yahoo' => 'yahoo', 'hotmail' => 'hotmail'], 'gmail', ['floating'=>false]); ?>
</div>

Textarea

Form::textarea($name, $label, $value = '', $rows = 3, $options = array(), $return = false)

$field = Hook:set('form_textarea', $field, $name, $label, $value, $rows, $options, $return)

Form::textarea('myTextarea', 'Label', '', 6);

checkbox

Form::checkbox($name, $label, $value = '', $is_checked = false, $options = array(), $return = false)

$field = Hook:set('form_checkbox', $field, $name, $label, $value, $checked, $options, $return)

<div class="form-check">Form::checkbox('myName', 'Label', '1');</div>
<div class="form-check">Form::checkbox('myName', 'Checked', '1', true);</div>
    

Checkbox with Custom Values (S/N, Y/N)

For checkboxes with custom values (like 'S'/'N' or 'Y'/'N'), add a hidden field before the checkbox to handle the unchecked state:

<input type="hidden" name="data[active]" value="N">
<?php Form::checkbox('data[active]', 'Active', 'S', true); ?>

With FormBuilder, use ->checkboxValues('S', 'N') to automatically handle this.

Single Switch

To display a checkbox as a switch, wrap it in a div with form-check form-switch classes:

<div class="form-check form-switch">
    <?php Form::checkbox('data[notifications]', 'Enable Notifications', '1', true); ?>
</div>

With FormBuilder, use ->formParams(['form-check-class' => 'form-switch']) to automatically add the switch style.

Checkboxes

Form::checkboxes($name, $list_of_checkbox, $selected_value, $inline, $options_group = [], $options_field = [], $return = false)

$field = Hook:set('form_checkboxes', $field, $name, $list_of_checkbox, $selected_value, $inline, $options_group, $options_field, $return)

Form::checkboxes('myCheckboxes', ['1' => 'One', '2' => 'Two', '3' => 'Three'], '2', true, ['label'=>'Select fields']);

Switch

Form::checkboxes('mySwitch', 
    ['1' => 'One', '2' => 'Two', '3' => 'Three'], 
    '2', 
    false, 
    ['label'=>'Select Switch', 'form-check-class'=>'form-switch']
);

Radio

Form::radio($name, $label, $value = '', $options = array(), $return = false)

$field = Hook:set('form_radio', $field, $name, $label, $value, $options, $return)

Form::radio('myRadio', 'Label', '1');

Radios

Form::radios($name, $list_of_radio, $selected_value = '', $inline = false, $options_group = [], $options_field = [], $return = false)

$field = Hook:set('form_radios', $field, $name, $list_of_radio, $selected_value, $inline, $options_group, $options_field)

Form::radios('myRadios', ['1' => 'One', '2' => 'Two', '3' => 'Three'], '2');

Select

Form::select($name, $label, $options = array(), $value = '', $multiple = false, $options = array(), $return = false)

$field = Hook:set('form_select', $field, $name, $label, $options, $value, $multiple, $options, $return)

Form::select('mySelect', 'Label', ['1' => 'One', '2' => 'Two', '3' => 'Three'], '2');

select options_group

Form::select('mySelect', 'Label', [
        'Group 1' => ['1' => 'One', '2' => 'Two', '3' => 'Three'], 
        'Group 2' => ['4' => 'Four', '5' => 'Five', '6' => 'Six']
], '2');

Action List

Form::actionList($name, $label, $list_options, $selected = '', $options = array(), $input_options = array(), $return = false)

$field = Hook:set('form_action_list', $field, $name, $label, $list_options, $selected, $options, $input_options)

Creates a clickable action list with hidden input for value storage. Perfect for filters, tabs, or any selection interface where you need clickable elements instead of a traditional select dropdown.

AllActiveSuspendedTrash
$filters = ['all' => 'All', 'active' => 'Active', 'suspended' => 'Suspended', 'trash' => 'Trash'];
Form::actionList('filter', 'Filter by status', $filters, 'trash', [
    'class' => 'filter-actions mb-3'
]);

With JavaScript callback

TechnologyDesignBusiness
$categories = ['tech' => 'Technology', 'design' => 'Design', 'business' => 'Business'];
Form::actionList('category', 'Select Category', $categories, 'tech', [
    'class' => 'btn-group',
    'item-class' => 'btn btn-outline-primary', 
    'active-class' => 'active'
], [
    'onchange' => 'alert("Selected:", this.value)',
    'data-callback' => 'handleCategoryChange'
]);

JavaScript API

The action_list provides a JavaScript API for programmatic control:

// Set value programmatically
Formaction_list.setValue('formfilter', 'active');

// Get current value
var currentValue = Formaction_list.getValue('formfilter');

// Add change listener
Formaction_list.onChange('formfilter', function(e) {
    console.log('New value:', e.target.value);
});

// Listen to custom event
document.addEventListener('action_listChange', function(e) {
    console.log('Changed from', e.detail.oldValue, 'to', e.detail.value);
});

Options

Available options for customizing the action list:

Container options ($options):
  • class - CSS class for the container
  • item-class - CSS class for each action item (default: 'link-action')
  • active-class - CSS class for the active item (default: 'active-action-list')
  • container-tag - HTML tag for container (default: 'div')
  • item-tag - HTML tag for items (default: 'span')
  • onchange - JavaScript to execute when selection changes (for backward compatibility)
Input options ($input_options):
  • class - CSS class for the hidden input
  • onchange - JavaScript to execute when value changes
  • data-* - Data attributes for the hidden input
  • required - Make the field required
  • invalid-feedback - Error message for validation
  • Other standard HTML5 input attributes
Loading...