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.
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.
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.
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
objects create HTML5 <button>
elements. In addition to the @css_classes
and @data
directives, they support the following class-specific 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:
<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
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
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:
<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>
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:
@css_classes
: An array of CSS class names to be applied to the component (usually the top-level tag of the component, but may be applied to other components that are more typically styled. See source code for the component.)@data
: A hash of data-*
attributes, mapping <name> => <value>
. For example, [ "id" => "1" ]
will create a data attribute data-id=1
for the component.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
.
@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!
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:
<!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>
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:
<!-- 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.
@components
NavbarBuilder
currently supports the following types of Bootstrap components:
NavBuilder
class.NavFormBuilder
class.NavButtonBuilder
classNavTextBuilder
classNavLinkBuilder
classEach 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
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.
The items in a NavBuilder
are represented using the NavItemBuilder
and NavDropdownBuilder
classes.
@active
: Optional. Make the specified item be highlighted as active in the nav. Set to false (default) or true.@display
: Optional. Setting @display
to disabled
will make the specified item be disabled, while setting it to hidden
will make it not show up at all.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
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>
@form
: The form, as a string or a FormBuilder
object.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>
@label
: The text for this button. Required.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>
@text
: The text for this item. Required.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>
@label
: The text for this link. Required.@url
: The url for this link. Required.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:
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 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:
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.
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:
<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>
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
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
.
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).
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.
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. |
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
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).
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. |
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
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:
<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
renders an <input>
tag with the type='password'
attribute. It is otherwise identical to a FormTextFieldBuilder
object.
FormNumberFieldBuilder
renders an <input>
tag with the type='number'
(integer only) attribute. It is otherwise identical to a FormTextFieldBuilder
object.
FormEmailFieldBuilder
renders an <input>
tag with the type='email'
attribute. It is otherwise identical to a FormTextFieldBuilder
object.
FormUrlFieldBuilder
renders an <input>
tag with the type='url'
attribute. It is otherwise identical to a FormTextFieldBuilder
object.
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
renders an <input>
tag with the type='search'
attribute. It is otherwise identical to a FormTextFieldBuilder
object.
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
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
renders a <select>
element, along with one or more child <option>
elements.
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.
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:
<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>
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:
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.
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
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:
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:
<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
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:
<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
renders an <input>
tag with the type='checkbox'
attribute. It uses the same directives as FormFieldBuilder
, but includes the following additional 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
renders an <input>
tag with the type='radio'
attribute. It is otherwise identical to a FormCheckboxFieldBuilder
object.
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:
<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>
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
.
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:
<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>
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. |
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.