Components

Bootsole comes with many classes, called components, that extend the basic HtmlBuilder class for additional functionality. For simplicity, we denote inheritance with the ← symbol, composition with the ♦ symbol, and traits with the + symbol. Of course the relationships are not a strictly linear hierarchy; see the documentation for each class for more details.

Basic Components

DropdownBuilder represents a basic dropdown menu. Typically, you will want to construct it implicitly in a parent object, such as a DropdownButtonBuilder or NavDropdownBuilder object. It uses the ItemCollection trait to implement a generic group of MenuItem objects.

Directives

Class method Directive Description
addItem @items Optional. An array of MenuItemBuilder objects, defined explicitly or implicitly as arrays.
align @align Optional. The alignment of the menu, relative to the parent object. Set to inherit (default), left, or right.

MenuItemBuilder represents a generic menu item, such as that which would be found in a navigation menu or button dropdown. It renders as an <li> HTML element.

Directives

Class method Directive Description
label @label Optional. The content to be displayed on this menu item.
url @url Optional. The URI that this menu item should link to.
active @active Optional. Render this item with the active class. Set to false (default) or true.
display @display Optional. Set to show (default), hidden, or disabled.

ButtonBuilder

ButtonBuilder objects create HTML5 <button> elements. In addition to the @css_classes and @data directives, they support the following class-specific directives:

Directives

Class method Directive Description
type @type Optional. The type of button. There are currently four types of buttons: submit, launch, cancel, and button. submit renders a button with the type='submit' attribute. launch renders a regular button with an additional data-toggle=modal attribute, and cancel adds a data-dismiss=modal attribute. These are used primarily for buttons that launch and close Bootstrap modals.
name @name Optional. The name of the button. Used to populate the name attribute in the <button> tag.
label @label Optional. The label to be displayed on this button.
active @active Optional. Render this button with the active class. Set to false (default) or true.
display @display Optional. Set to show (default), hidden, or disabled.

Similar to ButtonBuilder, but also contains a DropdownBuilder child object to achieve a Bootstrap button dropdown. The DropdownBuilder directives can be set directly in the definition of the DropdownButtonBuilder object.

Example:

$dbb = new BS\DropdownButtonBuilder([
    "@align" => "right",
    "@label" => "Press me!",
    "@css_classes" => ["btn-success"],
    "@items" => [
        "algebra" => [
            "@label" => "Algebra",
            "@url" => BS\URI_PUBLIC_ROOT. "courses/algebra"
        ],
        "calculus" => [
            "@label" => "Calculus",
            "@url" => BS\URI_PUBLIC_ROOT. "courses/calculus"

        ]
    ]
]);
echo $dbb->render();

Outputs:

Dropdown Button

<div class='btn-group'>
    <button type='button' name='' class='btn btn-success   dropdown-toggle'   data-toggle='dropdown' aria-expanded='false'>
        Press me! <span class='caret'></span>
    </button>
    <ul class='dropdown-menu dropdown-menu-right' role='menu'>
        <li class=' '><a role='menuitem' class=''  href='http://localhost/bootsole/public/courses/algebra'>Algebra</a></li>
        <li class=' '><a role='menuitem' class=''  href='http://localhost/bootsole/public/courses/calculus'>Calculus</a></li>

    </ul>
</div>

ButtonDropdownAddonBuilder

ButtonDropdownAddonBuilder is identical to DropdownButtonBuilder, except that it generates a "split" dropdown menu. This allows the associated button to perform a distinct action, beyond simply opening the dropdown menu.

ButtonGroupBuilder

ButtonGroupBuilder generates a Bootstrap button group. It contains a collection of ButtonBuilder, DropdownButtonBuilder, or ButtonDropdownAddonBuilder objects, implemented via the ItemCollection trait.

Use the @items directive to define the buttons contained in the button group.

Example:

$bgb = new BS\ButtonGroupBuilder([
    "@items" => [
        [
            "@type" => "button",
            "@label" => "Do it!",
            "@css_classes" => ["btn-warning"],
            "@name" => "action1",
            "@display" => "disabled"
        ],
        [
            "@type" => "button",
            "@label" => "Do it again!",
            "@css_classes" => ["btn-danger"],
            "@name" => "action2"
        ],                    
        [
            "@type" => "button",
            "@css_classes" => ["btn-danger"],
            "@name" => "dropdown_addon",
            "@align" => "inherit",
            "@items" => [
                "algebra" => [
                    "@label" => "Algebra",
                    "@url" => BS\URI_PUBLIC_ROOT. "courses/algebra"
                ],
                "calculus" => [
                    "@label" => "Calculus",
                    "@url" => BS\URI_PUBLIC_ROOT. "courses/calculus",
                    "@display" => "disabled"

                ]
            ]                
        ]
    ]
]);
echo $bgb->render();

Outputs:

Button Group

<div class='btn-group ' >

    <button type='button' name='action1' class='btn btn-warning  ' disabled >
        Do it!
    </button>

    <button type='button' name='action2' class='btn btn-danger  '  >
        Do it again!
    </button>

    <button type='button' name='dropdown_addon' class='btn btn-danger   dropdown-toggle'   data-toggle='dropdown' aria-expanded='false'>
        <span class='caret'></span>
    </button>
    <ul class='dropdown-menu ' role='menu'>
        <li class=' '><a role='menuitem' class=''  href='http://localhost/bootsole/public/courses/algebra'>Algebra</a></li>
    <li class=' disabled'><a role='menuitem' class=''  href='http://localhost/bootsole/public/courses/calculus'>Calculus</a></li>
    </ul>
</div>

HtmlAttributesBuilder

Many components have a top-level HTML tag, such as table, form, button, etc. You can add CSS classes and data-* attributes to these components using the following directives:

PageBuilder

The PageBuilder class builds a fully renderable HTML document. This will usually be your "top-level" templating object when developing websites and web applications. A PageBuilder object, in addition to the user-defined placeholders, accepts four directives: @name, @schema, @header, and @footer.

Directives

@name

Every page must have a unique name. This is used to reference the page, for example, when using the PageSchema class to automatically include relevant CSS and JS files.

@schema

The @schema directive takes a path to a JSON schema file. The schema file for pages consists of groups of pages, called manifests, and a corresponding list of paths to javascript and css files (relative to the PATH_JS_ROOT and PATH_CSS_ROOT directories):

{
    "terran" : {
        "pages": [
            "marine",
            "firebat",
            "ghost"
        ],
        "css": [
            "bootstrap-3.3.1.css",
            "font-awesome.min.css",
            "terran.css"
        ],
        "js": [
            "jquery-1.10.2.min.js",
            "bootstrap-3.3.1.js"
            ],
        "min_css": "min/terran.min.css",
        "min_js": "min/terran.min.js"    
    },
    "zerg" : {
        "pages": [
            "zergling",
            "hydralisk",
            "ultralisk"
        ],
        "css": [
            "bootstrap-3.3.1.css",
            "font-awesome.min.css",
            "zerg.css"
        ],
        "js": [
            "jquery-1.10.2.min.js",
            "bootstrap-3.3.1.js"
            ],
        "min_css": "min/zerg.min.css",
        "min_js": "min/zerg.min.js"    
    },    
    "default" : {
        "pages": [
            "about",
            "contact"
        ],
        "css": [
            "bootstrap-3.3.1.css",
            "font-awesome.min.css"
        ],
        "js": [
            "jquery-1.10.2.min.js",
            "bootstrap-3.3.1.js"     
            ],
        "min_css": "min/default.min.css",
        "min_js": "min/default.min.js"
    }
}

When a PageBuilder object is rendered, the schema file will be searched for a manifest group that matches the page's name. If found, it will automatically include the specified CSS and JS files into the <head> and <footer> elements, respectively. If a manifest is not found, the default manifest will be used. The default schema file is in schema/pages/pages.json.

Schemas can also be used to quickly toggle minified/merged Javascript and CSS for production environments. When the global constant JS_DEV in bootsole/config-bootsole.php is set to false, the single javascript file specified in min_js will be used instead of the files specified in js. Likewise, the CSS file specified in min_css will be used if CSS_DEV is set to false. To automatically generate the minified CSS and JS for each manifest group, use the script provided in build/build.php. The build script should only be used on the development server, immediately before pushing to the production server. This script requires write access to the directories in which the minified JS and CSS files are to be written; consult your server manual for more information on setting directory permissions for PHP.

For more information about minified Javascript and CSS, see Minification.

@header

Objects of type PageHeaderBuilder are used to represent the <head> block of a page. PageBuilder will look for a special placeholder in the page template, _header, to insert the rendered header. Therefore, any custom templates you write for PageBuilder should have a _header placeholder!

PageHeaderBuilder objects themselves have one directive, @css_includes, which represent the manifest group to be used in rendering the CSS. Typically there is no need to specify this directive explicitly - PageBuilder will do it automatically for you when it constructs the page!

@footer

Objects of type PageFooterBuilder are used to represent the <footer> block of a page. PageBuilder will look for a special placeholder in the page template, _footer, to insert the rendered footer.

They have one directive, @js_includes, which represent the manifest group to be used in rendering the JS. Typically there is no need to specify this directive explicitly - PageBuilder will do it automatically for you when it constructs the page!

Example

pages/page-default.html

<!DOCTYPE html>
<html lang="en">
    {{_header}}
    <body>
        <div class="container" role="main">
            <h1>{{heading_main}}</h1>
            <p>{{content}}</p>
        </div>
        {{_footer}}
    </body>    
</html>

...

require_once("config-site.php");

$header_content = [
    "author" => "Alex Weissman",
    "site_title" => SITE_TITLE,
    "page_title" => "Simple, nested templating for rendering Bootstrap themed pages with PHP",
    "description" => "A sample page for Bootsole",
    "favicon_path" => BS\URI_PUBLIC_ROOT . "css/favicon.ico"
];

$content = [
    "@header" => $header_content,
    "@name" => "test",
    "heading_main" => "Welcome to Bootsole",
    "content" => "Hey, I'm the content!"
];

$pb = new BS\PageBuilder($content);
echo $pb->render();

Output:

PageBuilder

<!DOCTYPE html>
<html lang="en">
    <!-- Common header includes for all account pages -->
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="A sample page for Bootsole">
        <meta name="author" content="Alex Weissman">

        <title>Bootsole | Simple, nested templating for rendering Bootstrap themed pages with PHP</title>

        <!-- Favicon -->
        <link rel="icon" type="image/x-icon" href="/bootsole/css/favicon.ico" />

        <link href='/bootsole/css/bootstrap-3.3.1.css' rel='stylesheet'>
        <link href='/bootsole/css/bootstrap-custom.css' rel='stylesheet'>
        <link href='/bootsole/css/font-awesome.min.css' rel='stylesheet'>
        <link href='/bootsole/css/tablesorter/theme.bootstrap.css' rel='stylesheet'>
        <link href='/bootsole/css/tablesorter/jquery.tablesorter.pager.css' rel='stylesheet'>
        <!-- Conditional formatting -->
    </head>
    <body> 
        <div class="container" role="main">
            <h1>Welcome to Bootsole</h1>
            <p>Hey, I'm the content!</p>
        </div>
        <footer>
            <div class="container">
              <p>
                  <a href="https://github.com/alexweissman/bootsole">Bootsole</a>, 2015
              </p>
            </div>
        </footer>
        <script src='/bootsole/js/jquery-1.10.2.min.js'></script>
        <script src='/bootsole/js/bootstrap-3.3.1.js'></script>
        <script src='/bootsole/js/bootsole.js'></script>
        <script src='/bootsole/js/tablesorter/jquery.tablesorter.min.js'></script>
        <script src='/bootsole/js/tablesorter/tables.js'></script>
        <script src='/bootsole/js/tablesorter/jquery.tablesorter.pager.min.js'></script>
        <script src='/bootsole/js/tablesorter/jquery.tablesorter.widgets.min.js'></script>
    </body>    
</html>

NavbarBuilder

The NavbarBuilder class constructs a Bootstrap navbar for a page. A navbar contains a list of components, specified by the @components directive:

$nb = new BS\NavbarBuilder([
    "brand_label" => "Bootsole is Great!",
    "brand_url" => "http://github.com/alexweissman/bootsole",
    "@components" => [
        "destroy" => [
            "@type" => "button",
            "@css_classes" => ["btn-danger"],
            "@label" => "Self-Destruct!"
        ],          
        // Implicitly declaring a NavBuilder object
        "main-menu" => [
            "@type" => "nav",
            "@align" => "right",
            "@items" => [
                "home" =>  [
                    "@active" => "true",
                    "@label" => "Home",
                    "@url" => BS\URI_PUBLIC_ROOT
                ],
                "about" => [
                    "@label" => "About",
                    "@url" => BS\URI_PUBLIC_ROOT. "about"
                ],
                "contact" => [
                    "@label" => "Contact",
                    "@url" => BS\URI_PUBLIC_ROOT. "contact"
                ]
            ]
        ]
    ]
]);

Outputs:

NavbarBuilder

<!-- Fixed navbar -->
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
    <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#main-nav-default" aria-expanded="false" aria-controls="main-nav-default">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
         <a class='navbar-brand' href='http://github.com/alexweissman/bootsole'>Bootsole is Great!</a>
        </div>
        <div id="main-nav-default" class="navbar-collapse collapse">
            <button type='button' class='btn btn-danger navbar-btn '>Self-Destruct!</button>
            <ul class='nav navbar-nav navbar-right'>
                <li class='active'><a href='/bootsole/'>Home</a></li>
                <li class=''><a href='/bootsole/about'>About</a></li>
                <li class=''><a href='/bootsole/contact'>Contact</a></li>
            </ul>
        </div><!--/.nav-collapse -->
    </div>
</nav>

The default navbar is a fixed top navbar specified in templates/navs/main-nav-default, but you may adapt this template to your own design needs.

Directives

@components

NavbarBuilder currently supports the following types of Bootstrap components:

Each component is built off of the abstract NavComponentBuilder class. To declare a component implicitly, rather than explicitly defining NavBuilder, NavFormBuilder, etc objects, use an array containing the @type directive:

@type object created
nav NavBuilder
form NavFormBuilder
button NavButtonBuilder
text NavTextBuilder
link NavLinkBuilder

All NavComponentBuilder objects support the @align directive, which describes how the component will be aligned within the navbar. Permitted values include left, right, and inherit. All templates for classes derived from NavComponentBuilder should use a _align placeholder, where the corresponding component will try to place the CSS classes for alignment.

All NavComponentBuilder objects support the @css_classes and @data directives.

NavBuilder

NavBuilder builds a collection of navigation items, which will be structured as an unordered list. The items are an array of NavItemBuilder objects, specified using the @items directive. Each NavItemBuilder object may be declared explicitly, or you can implicitly define them in nested subarrays:

$navb = new BS\NavBuilder([
    "@align" => "right",
    "@items" => [
        "home" =>  [
            "@active" => "true",
            "@label" => "Home",
            "@url" => BS\URI_PUBLIC_ROOT
        ],
        "about" => [
            "@label" => "About",
            "@url" => BS\URI_PUBLIC_ROOT. "about"
        ],
        "contact" => [
            "@label" => "Contact",
            "@url" => BS\URI_PUBLIC_ROOT. "contact"
        ]
    ]
]);

Output:

<ul class='nav navbar-nav navbar-right'>
    <li class='active'><a href='/bootsole/'>Home</a></li>
    <li class=''><a href='/bootsole/about'>About</a></li>
    <li class=''><a href='/bootsole/contact'>Contact</a></li>
</ul>

Every item in a NavBuilder has a name. This is automatically drawn from the keys in the @items array, or specified when you add the item via the addItem($name, $content) function.

Call the function setActiveItem($name) on a NavBuilder object to set the a nav item as active. All other items in the nav will automatically become inactive, so that only one menu item will be active at any time.

Use the function getItem($name) to get an item by name.

NavItemBuilder and NavDropdownBuilder

The items in a NavBuilder are represented using the NavItemBuilder and NavDropdownBuilder classes.

Directives

A NavDropdownBuilder builds a dropdown with submenu items. It is called in the same way as NavBuilder, with an @items directive specifying the child NavItemBuilder objects.

NavFormBuilder

NavFormBuilder wraps a form in a simple div with the navbar-form class. Bootstrap will automatically render the content as an inline form:

$navform = new BS\NavFormBuilder([
    "@align" => "right",
    "@form" => '<form role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>*
        <button type="submit" class="btn btn-default">Submit</button>
    </form>'    
]);

Output:

<div class='navbar-form navbar-right'>
    <form role="search">
        <div class="form-group">
          <input type="text" class="form-control" placeholder="Search">
        </div>*
        <button type="submit" class="btn btn-default">Submit</button>
    </form>
</div>

Directives

NavButtonBuilder

NavButtonBuilder renders a button with the navbar-btn CSS class. Bootstrap will automatically align the button in the navbar:

$navbtn = new BS\NavButtonBuilder([
    "@css_classes" => ["btn-danger"],
    "@label" => "Self-Destruct!"
]);

Output:

<button type='button' class='btn navbar-btn btn-danger '>Self-Destruct!</button>

Directives

NavTextBuilder

NavTextBuilder wraps the specified text in a <p> tag with the navbar-text CSS class. This formats it for display in the navbar:

$navtext = new BS\NavTextBuilder([
    "@text" => "Whazzup!!!"
]);

Output:

<p class='navbar-text '>Whazzup!!!</p>

Directives

NavLinkBuilder

NavLinkBuilder creates a non-nav link in your navbar, using the navbar-link CSS class:

$navlink = new BS\NavLinkBuilder([
    "@label" => "UserFrosting",
    "@url" => "https://www.userfrosting.com"
]);

Output:

<p class='navbar-text '><a href='https://www.userfrosting.com' class='navbar-link'>UserFrosting</a></p>

# Directives

TableBuilder

The TableBuilder class allows you to set templates for each column of a table, via the @columns directive. The content of the table is then supplied with an array of HtmlBuilder objects via the @rows directive. The column templates will then be used to render each data row.

The default table template, templates/tables/table-tablesorter-default, uses the tablesorter jQuery library to render dynamic, sortable, filterable, paginated tables.

A TableBuilder object is constructed as follows:

$content = [
    "@columns" => [...]
    "@rows" => [...]
];

Each member of the @columns array is a TableColumnBuilder object. A TableColumnBuilder object is a special templating class that renders the column header, but also maintains information about their corresponding cells in each row. It can be declared in the same way as any other HtmlBuilder object:

$column_content = [
    '@label' => 'Students',
    '@sorter' => 'metanum',
    '@sort_field' => 'num_students',
    '@intial_sort_direction' => 'asc',
    '@cell_template' => "<a class='btn btn-success' href='students.php?teacher_id={{teacher_id}}'>{{num_students}}</a>",
    '@empty_field' => 'num_students',
    '@empty_value' => '0',
    '@empty_template' => "Zero"
];

$column_template = "<h4>{{_label}}</h4>";

$column = new BS\TableColumnBuilder($column_content);
$column->setTemplate($column_template);

Thus when $column->render() is called, the template <h4>{{_label}}</h4> will be rendered with the supplied value of the @label directive. To set a template for the actual cell content of this column, use the @cell_template directive. When the parent TableBuilder object is rendered, it will attempt to replace the placeholders in @cell_template with the corresponding values in each row as specified by the @rows directive. In this way, TableBuilder can construct the entire table.

You can also specify an alternative template to use when a certain field in a row matches a certain value. This is useful when you want a cell to render differently when a value is 0 or empty. This is done using the @empty_template, @empty_field, and @empty_value directives. When a row has a field, as specified by @empty_field, whose value is equal to @empty_value, the @empty_template will be used instead of the usual @cell_template template.

For tablesorter tables, you can also specify sorting rules, using the @sorter and @sort_field directives. The field specified in @sort_field specifies which row field to sort on, and the @sorter specifies the sorting rule to be used. Use metatext for sorting alphabetically, and metanum to sort numerically. One easy way to sort by time is to use the metanum sorter in conjunction with a UTC timestamp as the @sort_field. Note that the field specified in @sort_field does not actually need to be rendered by the templates.

To set an initial sort direction, set the @initial_sort_direction directive to asc or desc. This will cause the table to be automatically sorted on the column in the specified direction upon page load.

You can of course define @columns and @rows directly in the table content array, without explicitly creating TableColumnBuilder and HtmlBuilder objects:


$table_content = [
    "@columns" => [
        "info" =>  [
            "@label" => "Teacher",
            "@sorter" => "metatext",
            "@sort_field" => "user_name",
            "@initial_sort_direction" => "asc",
            "@cell_template" => "
                    <div class='h4'>
                        <a href='user_details.php?id={{teacher_id}}'>{{display_name}} ({{user_name}})</a>
                    </div>
                    <div>
                        <i>{{title}}</i>
                    </div>
                    <div>
                        <i class='fa fa-envelope'></i> <a href='mailto:{{email}}'>{{email}}</a>
                    </div>"
        ],
        "num_students" => [
            "@label" => "Students",
            "@sorter" => "metanum",
            "@sort_field" => "num_students",
            "@cell_template" => "<a class='btn btn-success' href='students.php?teacher_id={{teacher_id}}'>{{num_students}}</a>",
            "@empty_field" => "num_students",
            "@empty_value" => "0",
            "@empty_template" => "Zero"
        ],
        "students" => [
            "@label" => "Student List",
            "@sorter" => "metanum",
            "@sort_field" => "num_students",
            "@cell_template" => "{{students}}",
            "@empty_field" => "students",
            "@empty_value" => [],
            "@empty_template" => "<i>None</i>"  
        ]      
    ],
    "@rows" => [
        "1" => [
            "teacher_id" => "1",
            "user_name" => "socrizzle",
            "display_name" => "Socrates",
            "title" => "Big Cheese",
            "email" => "socrates@athens.gov",
            "num_students" => "2",
            "students" => [
                "@template" => "<a class='btn btn-success' href='student_details.php?student_id={{student_id}}'>{{display_name}}</a>",
                "@array" => [
                    "A" => [
                        "student_id" => "1",
                        "display_name" => "Xenophon"
                    ],
                    "B" => [
                        "student_id" => "2",
                        "display_name" => "Plato"
                    ]
                ]
            ]
        ],
        "2" => [
            "teacher_id" => "2",
            "user_name" => "seamus",
            "display_name" => "Seamus",
            "title" => "Beanmaster",
            "email" => "seamus@cardboardbox.com",
            "num_students" => "0",
            "students" => []
        ],    
        "3" => [
            "teacher_id" => "3",
            "user_name" => "plato",
            "display_name" => "Plato",
            "title" => "Idealist",
            "email" => "plato@athens.gov",
            "num_students" => "1"
        ]
    ]
];

$table = new BS\TableBuilder($table_content);

Output:

TableBuilder

FormBuilder

FormComponentCollectionBuilder

The core FormComponentCollectionBuilder class allows building forms of arbitrary complexity. A FormComponentCollectionBuilder is basically a collection of form components (derived classes of the abstract FormComponentBuilder class), and/or other FormComponentCollectionBuilder objects. In this way components can be grouped, reused, and repeated in the same form without the need for separate placeholders for each group. The FormBuilder class is simply the highest-level (and often, only) collection of form components. For example, a form might be structured as such:

Components

Components can be added to a FormComponentCollectionBuilder object via the @components directive (array), or via the addComponent method. Each component can be a derived type of FormComponentBuilder object, or another FormComponentCollectionBuilder object. Many component objects can be declared implicitly via a subarray.

FormComponentCollectionBuilder also provides for some collection-wide properties, which can be set via the class methods or through array directives:

Directives

Class method Directive Description
labelWidth @label_width Optional. The width of form group labels, in columns (1-12), for horizontal forms
layout @layout Optional. The layout for the form. 'vertical' (default), 'horizontal', or 'inline'.
name @name Optional. The name of the collection. Used to populate the name attribute in the top-level HTML tag.
validators @validators Optional. An array mapping field names to strings containing data-* FormValidation rules.
values @values Optional. An array mapping field names to their initial values.

When a FormComponentCollectionBuilder is rendered, the layout and label_width will be passed along to its components. To mix and match layouts, you can use separate FormComponentCollectionBuilder components in a parent FormComponentCollectionBuilder or FormBuilder object.

Also on rendering, the appropriate validator and value will be passed along to the component with the corresponding name. This allows you to set the values and validators for all the components in one convenient array. This is especially useful when you want to load a set of data into a pre-existing form (for example, to update a database record), and for loading validation information from a validation schema. To load validation rules from a schema, you can use the Fortress package and create a ClientSideValidator object.

FormBuilder

The FormBuilder class extends the FormComponentCollectionBuilder class, and inherits all the functionality of that class. It also includes two additional directives, @method and @action, which correspond to the attributes of the top-level <form> tag.

Example


    $csv = new Fortress\ClientSideValidator(BS\PATH_SCHEMA . "forms/form-login.json", "en_US");
    $fb = new BS\FormBuilder([
    "@action" => "https://mysite.com/login/auth",
    "@layout" => "horizontal",
    "@label_width" => 2,
    "@components" => [
        'user_name' => [
            '@type' => 'text',
            '@label' => 'Username',
            '@placeholder' => 'Please enter the user name'
        ],
        'password' => [
            '@type' => 'password',
            '@label' => 'Password',
            '@placeholder' => 'Please enter your password'
        ],
        'submit' => new BS\FormButtonBuilder([
            "@type" => "submit",
            "@label" => "Log In",
            "@css_classes" => ["btn-primary", "btn-lg"]
        ])
    ],
    "@validators" => $csv->clientRules()
], "forms/form-login.html") ;

$fb->render();
Outputs:

Login Form

<form name='' method='post' action='https://mysite.com/login/auth' class='form-horizontal'>
    <div class='row'>
        <div class='col-md-6 col-md-offset-3'>
            <div class='form-group   '>
                <label class='control-label  col-sm-2'>Username</label>
                <div class='col-sm-10'>
                    <input type='text' class='form-control ' name='user_name' autocomplete='off' value='' placeholder='Please enter the user name' data-fv-notempty=true data-fv-notempty-message="'User name' is required."   >
                </div>
            </div>
            <div class='form-group   '>
                <label class='control-label  col-sm-2'>Password</label>
                <div class='col-sm-10'>
                    <input type='password' class='form-control ' name='password' autocomplete='off' value='' placeholder='Please enter your password' data-fv-notempty=true data-fv-notempty-message="'Password' is required."   >
                </div>
            </div>
            <div class='vert-pad'>
                <button type='submit' name='submit' class='btn btn-primary btn-lg  '  data-loading-text='Please wait...' >
                    Log In
                </button>
            </div>
        </div>
    </div>
</form>

Directives

Class method Directive Description
action @action The URI to which this form should submit.
method @method Optional. Specifies the HTTP method to use when sending form data (get (default) or post).

FormComponentBuilder

FormComponentBuilder is an abstract class that represents a form component. Form components include input fields, checkboxes, buttons, and more. As it is an abstract class, you cannot instantiate a FormComponentBuilder object directly. Instead you must instantiate one of its derived classes, which include FormGroupBuilder, FormFieldBuilder, and FormButtonBuilder.

Directives

A generic FormComponentBuilder object has four directives:

Class method Directive Description
name @name Required. The name of the component. Used to populate the name attribute in the appropriate HTML tag (<input>, <select>, etc.)
value @value Optional. The current value of the field.
default @default Optional. The default value of the field. Used as the value if value has not been set before rendering.
validator @validator Optional. The FormValidation validator for the field, as a string of data-* attributes.

The @name directive can be set explicitly when instantiating an object, or implicitly from an array key if it is defined implicitly. In the previous example, notice that the components did not have their @name directives set. Thus, they automatically took their names from the keys of the @components array (user_name, password, and submit).

FormGroupBuilder

The FormGroupBuilder class inherits from FormComponentBuilder. It serves as a wrapper for FormFieldBuilder objects, and implements Bootstrap's form groups. It also allows for associating a label with the field.

In most cases, you should create fields using the FormGroupBuilder class for optimal spacing and alignment. However if you really need to, you can still use naked FormFieldBuilder object as as components.

Directives

FormGroupBuilder objects have five directives, in addition to the ones they inherit from FormComponentBuilder:

Class method Directive Description
--- @type Required. Specifies what type of FormFieldBuilder object to create for this group. Can be any of text, password, number, email, url, color, select, select2, selecttime, hidden, textarea, checkbox, radio, switch, toggle, bootstrapradio.
label @label Optional. The label for the field. Automatically displayed above the field (vertical forms), to the left (horizontal forms), or hidden (inline forms).
display @display Optional. Display mode for the field. Can be show (default), disabled, readonly, or hidden. If set to hidden, the entire group will render as a null string. Useful for dynamically specifying which fields to render.
labelWidth @label_width Optional. The width of the form group label, in columns (1-12), for horizontal forms. Inherits from the parent FormFieldCollectionBuilder object if not explicitly set.
layout @layout Optional. The layout for the group. 'vertical' (default), 'horizontal', or 'inline'. Inherits from the parent FormFieldCollectionBuilder object if not explicitly set.

Fields

Every FormGroupBuilder object contains exactly one field object (derived classes of FormFieldBuilder). When a FormGroupBuilder is instantiated, the field object is automatically created using the @type directive of the FormGroupBuilder parent object, along with any additional content. It is possible to manually override the field object using the field method.

FormFieldBuilder

FormFieldBuilder is an abstract class that represents a form field object. These include all fields based on the HTML <input> tag (including checkboxes and radio buttons), as well as <textarea> and <select> fields. Bootsole does not currently support fields based on the <datalist>, <keygen>, or <output> tags (instead of <datalist>, we provide templating for the extremely popular select2 widget).

Directives

In addition to the directives that it inherits from FormComponentBuilder, FormFieldBuilder includes the following directives:

Class method Directive Description
display @display Optional. Display mode for the field. Can be show (default), disabled, readonly, or hidden. If set to hidden, the entire group will render as a null string. Useful for dynamically specifying which fields to render. Inherits from the parent FormGroupBuilder object if not explicitly set.
placeholder @placeholder Optional. A placeholder for the field. Used to populate the placeholder attribute of the HTML tag.
prepend @prepend Optional. Only available for fields that use the FormFieldAddonable trait. Sets the content for an input group addon in front of the field, and tells the FormFieldBuilder object to automatically wrap the field and addon in an input group.
append @append Optional. Only available for fields that use the FormFieldAddonable trait. Sets the content for an input group addon after the field and tells the FormFieldBuilder object to automatically wrap the field and addon in an input group.

Generating derived classes

Although FormFieldBuilder is an abstract class, it provides the static "factory" method generate for generating different types of derived classes. This is mainly used by FormGroupBuilder objects to determine what kind of field to create based on the @type directive. It takes two parameters, $type and $content, and returns the appropriate kind of FormFieldBuilder object. $type can be any of the types mentioned in the FormGroupBuilder documentation. $content is an array containing directives and placeholders for the new object.

FormTextFieldBuilder

FormTextFieldBuilder is the most generic type of <input>-based field that can be instantiated. It simply generates an HTML <input> element of type text, and uses the relevant FormComponentBuilder and FormFieldBuilder directives to populate the attributes.

Example:

$ftfb = new BS\FormTextFieldBuilder([
    '@name' => 'user_name',
    '@display' => 'disabled',
    '@placeholder' => 'Please enter the user name'
]);
$ftfb->render();

Outputs:

<input type='text' class='form-control ' name='user_name' autocomplete='off' value='' placeholder='Please enter the user name' disabled>

If you define it implicitly within a FormGroupBuilder, you can add a label and wrap it in a form group:

$ftfb = new BS\FormGroupBuilder([
    '@type' => 'text',
    '@name' => 'user_name',            
    '@display' => 'disabled',            
    '@label' => 'Username',
    '@placeholder' => 'Please enter the user name'
]);
$ftfb->render();
Outputs:

Basic text field

<div class='form-group   '>
    <label class='control-label  '>Username</label>
    <input type='text' class='form-control ' name='user_name' autocomplete='off' value='' placeholder='Please enter the user name' disabled>
</div>

FormPasswordFieldBuilder

FormPasswordFieldBuilder renders an <input> tag with the type='password' attribute. It is otherwise identical to a FormTextFieldBuilder object.

FormNumberFieldBuilder

FormNumberFieldBuilder renders an <input> tag with the type='number' (integer only) attribute. It is otherwise identical to a FormTextFieldBuilder object.

FormEmailFieldBuilder

FormEmailFieldBuilder renders an <input> tag with the type='email' attribute. It is otherwise identical to a FormTextFieldBuilder object.

FormUrlFieldBuilder

FormUrlFieldBuilder renders an <input> tag with the type='url' attribute. It is otherwise identical to a FormTextFieldBuilder object.

FormColorFieldBuilder

FormColorFieldBuilder renders an <input> tag with the type='color' attribute. It is otherwise identical to a FormTextFieldBuilder object. Note that the built-in color picker is not supported by all browsers.

FormSearchFieldBuilder

FormSearchFieldBuilder renders an <input> tag with the type='search' attribute. It is otherwise identical to a FormTextFieldBuilder object.

FormHiddenFieldBuilder

FormHiddenFieldBuilder renders an <input> tag with the type='hidden' attribute. It is otherwise identical to a FormTextFieldBuilder object, except that it does not support the @prepend, @append, or @placeholder directives.

FormTextAreaFieldBuilder

FormTextAreaFieldBuilder creates a <textarea> field. The API is basically the same as for FormTextFieldBuilder, except that it offers the @rows directive and rows method. This is used to set the number of text rows to display in the field. Note that we do not offer the cols method, because Bootstrap by default renders textareas to take up the entire width of the container. For a narrower field, you should use a container class, for example a Bootstrap grid element.

FormSelectFieldBuilder

FormSelectFieldBuilder renders a <select> element, along with one or more child <option> elements.

Items

Each child item is represented using a FormFieldOptionBuilder object. These can be defined explicitly, or implicitly as arrays. Items can be set through the @items directive or through the items method. FormSelectFieldBuilder uses the FormFieldSelectable trait to implement adding, getting, and selecting items.

Options can be selected in three ways: via the selectItem method, the selectItems method, or by the value method. selectItem takes the name of the option (based on its array key in @items, and selects exactly one item. selectItems takes a value, and selects all options that have that value. value serves as a wrapper for selectItems, but also sets the field multiple attribute if an array of values is specified.

Directives

In addition to the directives that it inherits from FormComponentBuilder, FormSelectBuilder includes the following directives:

Class method Directive Description
multiple @multiple Optional. Set to false (default) or true. Determines whether it is possible select more than one option.
items @items Optional. An array of FormFieldOptionBuilder objects, defined explicitly or as arrays.
itemClasses @item_classes Optional. An array of additional CSS classes to be applied to each child option. A shortcut for applying CSS classes individually to each element.

Example:

$fsfb = new BS\FormSelectFieldBuilder([
    '@type' => 'select',
    '@layout' => 'horizontal',
    '@label_width' => '2',
    '@label' => 'Title',
    '@items' => [
        'ta' => [
            '@label' => 'Teaching Assistant'
            ],
        'street_lord' => [
            '@label' => 'Street Lord'
            ],
        'adjunct' => [
            '@label' => 'Adjunct Instructor'
            ],
        'assistant' => [
            '@label' => 'Assistant Professor'
            ],
        'associate' => [
            '@label' => 'Associate Professor'
            ],
        'professor' => [
            '@label' => 'Professor'
            ],
        'emeritus' => [
            '@label' => 'Professor Emeritus'
            ]
    ],
    '@default' => 'emeritus',
    '@prepend' => "<span class='input-group-addon'><i class='fa fa-fw fa-mortar-board'></i></span>"
]);
Outputs:

Select field

<div class='form-group   '>
    <label class='control-label  col-sm-2'>
        Title
    </label>
    <div class='col-sm-10'>
        <div class='input-group'>
            <span class='input-group-addon'><i class='fa fa-fw fa-mortar-board'></i></span>
            <select class='form-control ' name='title' autocomplete='off'  placeholder=''>
                <option class='' value='ta'  >Teaching Assistant</option>
                <option class='' value='street_lord'  >Street Lord</option>
                <option class='' value='adjunct'  >Adjunct Instructor</option>
                <option class='' value='assistant'  >Assistant Professor</option>
                <option class='' value='associate'  >Associate Professor</option>
                <option class='' value='professor'  >Professor</option>
                <option class='' value='emeritus'  selected>Professor Emeritus</option>
            </select>
        </div>
    </div>
</div>

FormFieldOptionBuilder

This class builds a selectable item in a FormSelectFieldBuilder, FormSelect2FieldBuilder, FormSelectTimeFieldBuilder, FormToggleFieldBuilder, or FormBootstrapRadioBuilder object. It uses the FormFieldSelectableItem trait to implement the following directives:

Directives

Class method Directive Description
itemValue @item_value Optional. The value associated with this particular item. If not specified, will be automatically taken from the key in the @items array of the parent object.
label @label Optional. The label to display for this option. If not specified, will default to the item value.
title @title Optional. Sets the title attribute for this option. Useful for creating tooltips for the FormFieldBootstrapRadioBuilder components.
selected @selected Optional. Specifies whether this item should be set as a currently selected item. Set to false (default) or true.

There is typically no need to define these objects explicitly. Instead, they can be defined implicitly in the @items directive of a parent object. Items with an item_value that matches the parent value will be automatically selected upon construction.

FormSelect2FieldBuilder

This class is identical to FormSelectFieldBuilder, except that it adds the select2 class to the <select> tag. The select2 class tells Bootsole to initialize the field as a select2 element. If you aren't familiar with Select2, it is a extremely popular enhancement for standard <select> elements. From their website:

Select2 gives you a customizable select box with support for searching, tagging, remote data sets, infinite scrolling, and many other highly used options.

Note: to use FormSelect2FieldBuilder, you will need the relevant CSS and JS files. You can download them from the Select2 website, or use the version included with this repository in the public directory. You will also need the following JS code to perform basic initialization:

// Initialize select2 dropdowns, if enabled
if (jQuery().select2){
    $('.select2').select2();
} else {
    console.error("The select2 plugin has not been added.");
}

This code is included already in public/js/bootsole.js.

FormSelectTimeFieldBuilder

FormSelectTimeFieldBuilder is a special modification of FormSelectFieldBuilder that generates a list of times in a specific range, with a specified increment. It will try to render as a select2 field, if the library is available. It uses the following additional directives:

Directives

Class method Directive Description
timeStart @time_start Optional. The start time. Should be a time that can be parsed by strtotime. Default is 12:00 am.
timeEnd @time_end Optional. The end time. Should be a time that can be parsed by strtotime. Default is 11:45 pm.
timeIncrement @time_increment Optional. The time increment, in minutes. Default is 15.

Example:

$fstb = new BS\FormGroupBuilder([
    '@type' => 'selecttime',
    '@layout' => 'horizontal',
    '@label' => 'Wakeup Call',
    '@prepend' => "<span class='input-group-addon'><i class='fa fa-fw fa-clock-o'></i></span>",
    '@time_start' => '5:00 am',
    '@time_end' => '12:00 pm',
    '@time_increment' => 30,
    '@placeholder' => 'When?',
    '@default' => '11:00 am'
]);
echo $fstb->render();

Outputs:

Select Time

<div class='form-group   '>
    <label class='control-label  col-sm-2'>Wakeup Call</label>
    <div class='col-sm-10'>
        <div class='input-group'>
            <span class='input-group-addon'><i class='fa fa-fw fa-clock-o'></i></span>
            <select class='form-control select2 ' name='wakeup' autocomplete='off'  placeholder='When?'   >
                <option></option>
                <option class='' value='5:00 am'  >5:00 am</option>
                <option class='' value='5:30 am'  >5:30 am</option>
                <option class='' value='6:00 am'  >6:00 am</option>
                <option class='' value='6:30 am'  >6:30 am</option>
                <option class='' value='7:00 am'  >7:00 am</option>
                <option class='' value='7:30 am'  >7:30 am</option>
                <option class='' value='8:00 am'  >8:00 am</option>
                <option class='' value='8:30 am'  >8:30 am</option>
                <option class='' value='9:00 am'  >9:00 am</option>
                <option class='' value='9:30 am'  >9:30 am</option>
                <option class='' value='10:00 am'  >10:00 am</option>
                <option class='' value='10:30 am'  >10:30 am</option>
                <option class='' value='11:00 am'  selected>11:00 am</option>
                <option class='' value='11:30 am'  >11:30 am</option>
                <option class='' value='12:00 pm'  >12:00 pm</option>
            </select>
        </div>
    </div>
</div>

FormToggleFieldBuilder

FormToggleFieldBuilder generates a set of checkboxes or radio buttons, styled as Bootstrap toggle buttons. It extends the FormSelectFieldBuilder class, so each item is a FormFieldOptionBuilder object. However, the items are rendered as <input> elements rather than <option> elements.

The @multiple directive determines whether the items are rendered as <input> elements with type=checkbox or type=radio . The @display and @name directives are automatically passed down to the child elements upon rendering.

Example:

$ftfb = new BS\FormGroupBuilder([
    '@type' => 'toggle',
    `@name' => 'beard',
    '@label' => 'Beard',
    '@multiple' => "true",
    '@prepend' => "<span class='input-group-addon'><i class='fa fa-fw fa-trophy'></i></span>",
    '@item_classes' => [
        'btn-primary'
    ],
    '@items' => [
        'fluffy' => [
            '@label' => 'Fluffy'
        ],
        'scraggly' => [
            '@label' => 'Scraggly'
        ],
        'pointy' => [
            '@label' => 'Pointy'
        ]
    ],
    '@display' => 'disabled'
]);
echo $ftfb->render();

Outputs:

Toggle

<div class='form-group   '>
    <label class='control-label  '>Beard</label>
    <div class='input-group'>
        <span class='input-group-addon'><i class='fa fa-fw fa-trophy'></i></span>
        <div class='btn-group' data-toggle='buttons'>

        <label class='btn btn-primary  disabled'>
            <input class='form-control' type='checkbox' name='beard' value='fluffy'   disabled> Fluffy
        </label>

        <label class='btn btn-primary  disabled'>
            <input class='form-control' type='checkbox' name='beard' value='scraggly'   disabled> Scraggly
        </label>

        <label class='btn btn-primary  active disabled'>
            <input class='form-control' type='checkbox' name='beard' value='pointy'   disabled checked> Pointy
        </label>

        </div>
    </div>
</div>

Note: Bootstrap toggle buttons require some custom CSS to properly render options that are both selected and disabled. Please see public/css/bootstrap-custom.css.

FormCheckboxFieldBuilder

FormCheckboxFieldBuilder renders an <input> tag with the type='checkbox' attribute. It uses the same directives as FormFieldBuilder, but includes the following additional directives:

Directives

Class method Directive Description
itemValue @item_value Required. The value associated with this particular checkbox.
text @text Optional. The text to display to the right of the checkbox.
title @title Optional. Sets the title attribute for this option.
selected @selected Optional. Specifies whether this item should be set as a currently selected item. Set to false (default) or true.

You can use the value method on a checkbox as well. However, it works differently from the way value would work on say, a text field. For checkboxes (and radios), the value function will check whether the parameter is equal to the item_value for the checkbox. If so, it will set the checkbox to selected. If not, it will deselect the checkbox. This allows you to preset checkboxes in the same way as you would other fields.

FormRadioFieldBuilder

FormRadioFieldBuilder renders an <input> tag with the type='radio' attribute. It is otherwise identical to a FormCheckboxFieldBuilder object.

FormSwitchFieldBuilder

FormSwitchFieldBuilder is the same as FormCheckboxFieldBuilder, but adds the switch class to the <input> element. The switch class tells Bootsole to initialize the field as a Bootstrap Switch element. This allows you to graphically style the checkbox as an on-off toggle switch:

$fsfb = new BS\FormGroupBuilder([
    '@type' => 'switch',
    '@name' => "tos",
    '@label' => "TOS",
    '@text' => "I agree to the Terms and Conditions",
    '@text_on' => "Yes",
    '@text_off' => "No",
    '@item_value' => "yessir"
]);
echo $fsfb->render();

Outputs:

Switch

<div class='form-group   '>
    <label class='control-label  col-sm-4'>TOS</label>
    <div class='col-sm-8'>
        <div>
            <input type='checkbox' class='form-control bootstrapswitch ' name='tos' value='yessir' title=''  checked  data-on-text='Yes' data-off-text='No'> 
            I agree to the Terms and Conditions
        </div>
    </div>
</div>

Directives

Class method Directive Description
textOn @text_on Optional. The text to display for the switch in 'on' (checked) mode.
textOff @text_off Optional. The text to display for the switch in 'off' (unchecked) mode.

Note: to use FormSwitchFieldBuilder, you will need the relevant CSS and JS files. You can download them from the Bootstrap Switch website, or use the version included with this repository in the public directory. You will also need the following JS code to perform basic initialization:

// Initialize bootstrap switches, if enabled
if (jQuery().bootstrapSwitch){
    $('.bootstrapswitch').bootstrapSwitch();
} else {
    console.error("The bootstrap-switch plugin has not been added.");
}

This code is included already in public/js/bootsole.js.

FormBootstrapRadioBuilder

This class uses the Bootstrap Radio plugin to tie a group of buttons to a hidden <input> element, simulating a group of radio buttons. Thus, you can read the selected value from an ordinary <input> element.

Example:

$fbrfb = new BS\FormGroupBuilder([
    '@type' => 'bootstrapradio',
    '@name' => 'school',
    '@label' => 'School',
    '@items' => [
        'epicurist' => [
            '@title' => 'Epicurist.  Relax and enjoy life.',
            '@label' => "<i class='fa fa-cutlery'></i>"
        ],
        'futurist' => [
            '@title' => 'Futurist.  Cyborgs unite!',
            '@label' => "<i class='fa fa-space-shuttle'></i>"
        ],
        'stoic' => [
            '@title' => 'Stoic.  Grin and bear it.',
            '@label' => "<i class='fa fa-tree'></i>"
        ]
    ]                  
]);
echo $fbrfb->render();

Outputs:

Toggle

<div class='form-group   '>
    <label class='control-label  '>School</label>
    <div>
        <input value="epicurist" name="school" type="hidden">
        <button type='button' class='bootstrapradio ' name='school' value='epicurist' title='Epicurist.  Relax and enjoy life.'  data-selected='true' data-size='xs'>
            <i class='fa fa-cutlery'></i>
        </button> 
        <button type='button' class='bootstrapradio ' name='school' value='futurist' title='Futurist.  Cyborgs unite!'  data-selected='false' data-size='xs'>
            <i class='fa fa-space-shuttle'></i>
        </button> 
        <button type='button' class='bootstrapradio ' name='school' value='stoic' title='Stoic.  Grin and bear it.'  data-selected='false' data-size='xs'>
            <i class='fa fa-tree'></i>
        </button> 
    </div>
</div>

Directives:

Class method Directive Description
multiple @multiple Optional. Set to false (default) or true. Determines whether it is possible select more than one option.
items @items Optional. An array of FormFieldOptionBuilder objects, defined explicitly or as arrays.
size @size Optional. The size of the options. Can be any of the Bootstrap button size classes: (xs, sm, lg, or block).
itemClasses @item_classes Optional. An array of additional CSS classes to be applied to each child option. A shortcut for applying CSS classes individually to each element.

FormButtonBuilder

This class builds an HTML <button> element to associate with the form. It is simply a wrapper for a ButtonBuilder or ButtonGroupBuilder object. It will automatically generate a ButtonBuilder object from the supplied content.