Milk Admin

ListBuilder Styling

Complete guide for customizing list appearance using the field-first pattern. Lists display data as Bootstrap cards in a responsive grid layout. Apply CSS classes directly to fields and boxes with clean, readable code.

Understanding List Structure

The list plugin uses a box_attrs array to control the appearance of different elements. Here's the default structure:

Attribute Key Element Default Classes
form Form wrapper card-body-overflow js-list-form container-fluid
container Grid container (row) row g-3 js-box-container
col Column wrapper for each box col-12 col-md-6 col-lg-4
box Card/box element card h-100 js-box-item
box.header Box header (checkbox + actions) card-header d-flex justify-content-between align-items-center
box.body Box body (field rows) card-body
box.footer Box footer card-footer
field.row Single field container row mb-2 border-bottom pb-2
field.label Field label column col-5 fw-bold text-muted
field.value Field value column col-7
checkbox.wrapper Checkbox wrapper form-check

Quick Start

Quick Color Themes

$list = \Builders\ListBuilder::create($model, 'products_list')
    ->boxColor('primary')    // Blue theme
    ->boxColor('success')    // Green theme
    ->boxColor('danger')     // Red theme
    ->boxColor('warning')    // Yellow theme
    ->getResponse();
echo $list['html'];

Custom Box Classes

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Combine multiple Bootstrap card classes
    ->boxClass('card shadow-sm border-0')
    ->getResponse();
echo $list['html'];

Grid Layout

Responsive Columns

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Set responsive grid: 1 col on mobile, 2 on tablet, $cols on desktop
    ->gridColumns($cols)
    ->getResponse();
echo $list['html'];

Note: Default is col-12 col-md-6 col-lg-4 (1 column on mobile, 2 on tablet, 3 on desktop)

Custom Container and Column Classes

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Customize the container wrapper
    ->containerClass('row g-4 justify-content-center')

    // Customize individual column wrappers
    ->colClass('col-12 col-sm-6 col-lg-4 col-xl-3')

    ->getResponse();
echo $list['html'];

Box Styling

Box Component Classes

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Style the entire box
    ->boxClass('card shadow-lg border-primary')

    // Style box header
    ->boxHeaderClass('bg-primary text-white fw-bold')

    // Style box body
    ->boxBodyClass('bg-light')

    // Style box footer
    ->boxFooterClass('bg-secondary text-white text-center')

    ->getResponse();
echo $list['html'];

Alternating Box Colors

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Alternate between two CSS classes
    ->boxClassAlternate('border-primary', 'border-success')
    ->getResponse();
echo $list['html'];

Conditional Box Classes

$list = \Builders\ListBuilder::create($model, 'orders_list')
    // Highlight cancelled orders in red
    ->classByValue( 'cancelled', 'border-danger bg-danger bg-opacity-10')

    // Highlight high-value orders in yellow (total > 1000)
    ->field('total')
    ->classByValue(1000, 'border-warning shadow-lg', '>')

    // Supported operators: '==', '>', '<', '>=', '<=', '!=', 'contains'
    ->getResponse();
echo $list['html'];

Field-First Styling

The field-first pattern allows you to apply styling directly to each field using method chaining. This keeps all field configurations (data, display, and styling) in one place.

Basic Field Styling

$list = \Builders\ListBuilder::create($model, 'sales_list')
    // Style specific fields
    ->field('amount')
        ->label('Total Amount')
        ->class('text-success fw-bold fs-5')

    ->field('status')
        ->label('Status')
        ->class('text-center badge bg-primary')

    ->field('customer_name')
        ->label('Customer')
        ->class('fw-semibold text-primary')

    ->getTable();

Conditional Field Styling

Apply CSS classes when a field matches a specific value using classValue().

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Status field with color coding
    ->field('status')
        ->label('Status')
        ->classValue('active', 'badge bg-success')
        ->classValue('inactive', 'badge bg-danger')
        ->classValue('pending', 'badge bg-warning')

    // Stock with conditional styling
    ->field('stock')
        ->label('Stock')
        ->classValue(10, 'text-danger fw-bold fs-4', '<')   // Red if < 10
        ->classValue(50, 'text-warning', '<')               // Orange if < 50
        ->classValue(50, 'text-success', '>=')              // Green if >= 50

    // Price highlighting
    ->field('price')
        ->label('Price')
        ->classValue(100, 'text-success fs-5 fw-bold', '>') // Large green if > 100
        ->class('text-end')

    ->getTable();

// Supported operators: '==', '!=', '>', '<', '>=', '<=', 'contains'

Style Based on Another Field

Apply CSS classes to a field based on the value of a different field using classOtherValue().

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Highlight price when product has discount
    ->field('price')
        ->label('Price')
        ->classOtherValue('has_discount', true, 'text-success fw-bold fs-4')
        ->class('text-end')

    // Show name in muted color if not in stock
    ->field('name')
        ->label('Product Name')
        ->classOtherValue('stock', 0, 'text-muted text-decoration-line-through')
        ->link('?page=products&action=edit&id=%id%')

    // Highlight quantity based on stock status
    ->field('quantity')
        ->label('Quantity')
        ->classOtherValue('stock_status', 'low', 'text-danger fw-bold')
        ->classOtherValue('stock_status', 'out', 'text-danger text-decoration-line-through')

    ->getTable();

Global Field Classes

You can also set global styles for all field rows, labels, and values:

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Style all field rows
    ->fieldRowClass('mb-3 pb-2 border-bottom')

    // Style all field labels
    ->fieldLabelClass('col-4 fw-bold text-primary')

    // Style all field values
    ->fieldValueClass('col-8 text-end')

    // Then override specific fields with field-first pattern
    ->field('price')
        ->label('Price')
        ->class('text-success fs-4 fw-bold')  // Override global value class

    ->getResponse();
echo $list['html'];

Custom Box Template

You can replace the default box template with your own custom template file. The template receives the following variables:

  • $box_attrs - Array of box attributes
  • $box_item_attrs - Specific attributes for this box (with dynamic classes)
  • $fields_data - Array of field objects with label, value, type, classes, and attrs
  • $checkbox - HTML for checkbox (if present)
  • $actions - HTML for actions (if present)

Example: Custom Template for Posts

Step 1: Create the custom template file at Modules/Posts/Views/custom-box.php:

<?php
!defined('MILK_DIR') && die();
?>

<div <?php Theme\Template::addAttrs($box_attrs, 'col'); ?>>
    <div <?php Theme\Template::addAttrs(['box' => $box_item_attrs], 'box'); ?>>
        <div <?php Theme\Template::addAttrs($box_attrs, 'box.body'); ?>>
            <h2><?php _p($fields_data['title']->value) ?></h2>
            <p><?php _pt($fields_data['content']->value) ?></p>
        </div>
         <?php if ($checkbox || $actions) { ?>
            <div <?php Theme\Template::addAttrs($box_attrs, 'box.footer'); ?>>
                <?php echo $checkbox; ?>
                <?php echo $actions; ?>
            </div>
        <?php } ?>
    </div>
</div>

Step 2: Use the template in your controller:

// In PostsController.php
$response['html'] = ListBuilder::create($this->model, 'idTablePosts')
    ->field('content')
        ->truncate(50)

    ->gridColumns(1)

    // Set custom box template
    ->setBoxTemplate(__DIR__ . '/Views/custom-box.php')

    ->setDefaultActions()
    ->render();

Template Variables Reference

Your custom template has access to these variables:

Variable Type Description
$box_attrs array All box attributes (col, box, box.header, box.body, box.footer)
$box_item_attrs array Attributes for this specific box (includes dynamic classes)
$fields_data array Associative array: $fields_data['field_name']->value, ->label, ->type
$checkbox string HTML for checkbox (empty if no bulk actions)
$actions string HTML for row actions (empty if no actions)

Accessing Field Data

<!-- Access specific field values -->
<?php _p($fields_data['title']->value) ?>
<?php _p($fields_data['price']->value) ?>
<?php _p($fields_data['created_at']->value) ?>

<!-- Check field type -->
<?php if ($fields_data['description']->type == 'html') {
    _ph($fields_data['description']->value);
} else {
    _p($fields_data['description']->value);
} ?>

<!-- Loop through all fields -->
<?php foreach ($fields_data as $field_name => $field) : ?>
    <strong><?php _pt($field->label); ?>:</strong>
    <?php _p($field->value); ?>
<?php endforeach; ?>

Complete Styling Example

$model = new \Models\ProductModel();

$list = \Builders\ListBuilder::create($model, 'products_list')
    // Query configuration
    ->where('deleted = ?', [0])
    ->orderBy('created_at', 'desc')
    ->limit(24)

    // Grid Layout: responsive columns
    ->gridColumns(3)

    // Container styling
    ->containerClass('row g-4')

    // Box-level styling
    ->boxClass('card h-100 shadow-sm')
    ->boxColor('primary')

    // Conditional box highlighting
    ->classByValue('stock', 0, 'border-danger border-3')
    ->classByValue('status', 'featured', 'shadow-lg border-warning border-2')

    // Box component styling
    ->boxHeaderClass('bg-gradient text-white')
    ->boxBodyClass('p-3')

    // Global field styling
    ->fieldRowClass('mb-2 pb-2')
    ->fieldLabelClass('col-5 text-muted small')
    ->fieldValueClass('col-7 fw-semibold')

    // Field-first styling for specific fields
    ->field('name')
        ->label('Product Name')
        ->link('?page=products&action=edit&id=%id%')
        ->classOtherValue('featured', true, 'fw-bold text-primary')

    ->field('price')
        ->label('Price')
        ->class('text-success fs-5 fw-bold text-end')
        ->classValue(100, 'text-danger fs-4', '>')  // Extra large red if > 100

    ->field('stock')
        ->label('Stock')
        ->class('text-center')
        ->classValue(10, 'text-danger fw-bold', '<')
        ->classValue(0, 'badge bg-danger', '==')

    ->field('status')
        ->label('Status')
        ->classValue('active', 'badge bg-success')
        ->classValue('inactive', 'badge bg-secondary')
        ->classValue('featured', 'badge bg-warning text-dark')

    ->field('category')
        ->label('Category')
        ->class('text-muted')

    // Actions
    ->setDefaultActions()

    ->getTable();

Method Reference

Field-First Styling Methods

Method Parameters Description Example
field() $key Select field for styling ->field('status')
class() $classes Set CSS classes for field value ->class('fw-bold text-primary')
classValue() $value, $classes, $operator Conditional classes based on field value ->classValue('active', 'badge bg-success')
classOtherValue() $field, $value, $classes, $operator Conditional classes based on other field ->classOtherValue('featured', true, 'fw-bold')

Global Field Styling Methods

Method Parameters Description
fieldRowClass() $classes CSS classes for all field row containers
fieldLabelClass() $classes CSS classes for all field labels
fieldValueClass() $classes CSS classes for all field values

Box & Layout Methods

Method Parameters Description
boxColor() $color Quick theme colors (primary, success, danger, warning, info, light, dark)
boxClass() $classes Custom CSS classes for box element
boxHeaderClass() $classes CSS classes for box header
boxBodyClass() $classes CSS classes for box body
boxFooterClass() $classes CSS classes for box footer
boxClassAlternate() $odd_classes, $even_classes Alternate box colors
classByValue() $value, $classes, $operator Conditional box classes based on field value
containerClass() $classes CSS classes for grid container
colClass() $classes CSS classes for column wrappers
gridColumns() $cols Set responsive grid columns (e.g., 2, 3, 4)
checkboxWrapperClass() $classes CSS classes for checkbox wrapper
setBoxTemplate() $template_path Set custom box template file (absolute path)

Supported Comparison Operators

  • == - Equal to (default)
  • != - Not equal to
  • > - Greater than
  • < - Less than
  • >= - Greater than or equal to
  • <= - Less than or equal to
  • contains - String contains value

Best Practices

  • Use field-first pattern: Keep all configuration for a field (label, type, styling) together
  • Combine global and specific styling: Set global field styles with fieldLabelClass(), then override specific fields with field()->class()
  • Use semantic classes: Prefer Bootstrap utility classes (badge, text-success) for consistency
  • Chain multiple classValue(): Apply different styles for different conditions on the same field
  • Test responsive grid: Use gridColumns() to ensure proper display on all devices
  • Accessibility: Don't rely solely on color; use text, icons, or badges for critical information
Loading...