├── LICENSE.txt
├── README.md
├── composer.json
├── contrib
└── pre-commit
├── package-lock.json
├── package.json
├── src
├── BootstrapUIPlugin.php
├── Command
│ ├── BootstrapCommand.php
│ ├── CopyLayoutsCommand.php
│ ├── InstallCommand.php
│ └── ModifyViewCommand.php
└── View
│ ├── Helper
│ ├── BreadcrumbsHelper.php
│ ├── FlashHelper.php
│ ├── FormHelper.php
│ ├── HtmlHelper.php
│ ├── OptionsAwareTrait.php
│ ├── PaginatorHelper.php
│ └── Types
│ │ ├── Classes.php
│ │ ├── Element.php
│ │ ├── Type.php
│ │ └── TypeInterface.php
│ ├── UIView.php
│ ├── UIViewTrait.php
│ └── Widget
│ ├── BasicWidget.php
│ ├── ButtonWidget.php
│ ├── DateTimeWidget.php
│ ├── FileWidget.php
│ ├── InputGroupTrait.php
│ ├── SelectBoxWidget.php
│ └── TextareaWidget.php
├── templates
├── bake
│ ├── Template
│ │ ├── add.twig
│ │ ├── edit.twig
│ │ ├── index.twig
│ │ ├── login.twig
│ │ └── view.twig
│ └── element
│ │ ├── form.twig
│ │ └── tb_actions.twig
├── element
│ └── flash
│ │ └── default.php
└── layout
│ ├── default.php
│ └── examples
│ ├── cover.php
│ ├── dashboard.php
│ └── signin.php
└── webroot
├── css
├── cover.css
├── dashboard.css
└── signin.css
├── font
└── bootstrap-icon-sizes.css
└── img
└── baked-with-cakephp.svg
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014 Jad Bitar
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all
11 | copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 | SOFTWARE.
20 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bootstrap UI
2 |
3 | [![Build Status][ico-ga]][ga]
4 | [![Coverage Status][ico-coverage]][coverage]
5 | [![Total Downloads][ico-downloads]][package]
6 | [![License][ico-license]][license]
7 |
8 | [ico-ga]: https://img.shields.io/github/actions/workflow/status/FriendsOfCake/bootstrap-ui/ci.yml?branch=master&style=flat-square
9 | [ico-coverage]: https://img.shields.io/codecov/c/github/FriendsOfCake/bootstrap-ui.svg?style=flat-square
10 | [ico-downloads]: https://img.shields.io/packagist/dt/friendsofcake/bootstrap-ui.svg?style=flat-square
11 | [ico-license]: https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square
12 |
13 | [ga]: https://github.com/FriendsOfCake/bootstrap-ui/actions?query=workflow%3ACI+branch%3Amaster
14 | [coverage]: https://codecov.io/github/FriendsOfCake/bootstrap-ui
15 | [package]: https://packagist.org/packages/friendsofcake/bootstrap-ui
16 | [license]: LICENSE.txt
17 |
18 | Transparently use [Bootstrap 5][bs] with [CakePHP 5][cakephp].
19 |
20 | For version info see [version map](https://github.com/FriendsOfCake/bootstrap-ui/wiki#version-map).
21 |
22 | ## Requirements
23 |
24 | * CakePHP 5.x
25 | * Bootstrap 5.3.x
26 | * npm 6.x
27 | * Bootstrap Icons 1.11.x
28 |
29 | ## What's included?
30 |
31 | - FlashHelper (element types: `error`, `info`, `success`, `warning`)
32 | - FormHelper (align: `default`, `inline`, `horizontal`)
33 | - BreadcrumbsHelper
34 | - HtmlHelper (components: `badge`, `icon`)
35 | - PaginatorHelper
36 | - Widgets (`basic`, `button`, `datetime`, `file`, `select`, `textarea`)
37 | - Example layouts (`cover`, `signin`, `dashboard`)
38 | - Bake templates
39 |
40 | ## Table of contents
41 |
42 | - [Installation](#installation)
43 | - [Setup](#setup)
44 | - [Using the Bootstrap commands](#using-the-bootstrap-commands)
45 | - [Manual setup](#manual-setup)
46 | - [BootstrapUI layouts](#bootstrapui-layouts)
47 | - [Including the Bootstrap framework](#including-the-bootstrap-framework)
48 | - [Bake templates](#bake-templates)
49 | - [Usage](#usage)
50 | - [Contributing](#contributing)
51 | - [License](#license)
52 |
53 | ## Installation
54 |
55 | `cd` to the root of your app folder (where the `composer.json` file is) and run the following [Composer][composer]
56 | command:
57 |
58 | ```
59 | composer require friendsofcake/bootstrap-ui
60 | ```
61 |
62 | Then load the plugin using CakePHP's console:
63 |
64 | ```
65 | bin/cake plugin load BootstrapUI
66 | ```
67 |
68 | ## Setup
69 |
70 | You can either use the Bootstrap commands to make the necessary changes, or do them manually.
71 |
72 | ### Using the Bootstrap commands
73 |
74 | 1. To install the Bootstrap assets (Bootstrap's CSS/JS files) via npm you can use the `install`
75 | command, or [install them manually](#installing-bootstrap-assets-via-npm):
76 |
77 | ```
78 | bin/cake bootstrap install
79 | ```
80 |
81 | This will fetch all assets, copy the distribution assets to the BootstrapUI plugin's webroot directory, and symlink
82 | (or copy) them to your application's `webroot` directory.
83 |
84 | If you want to install the latest minor versions of the assets instead of the exact pinned ones, you can use the
85 | `--latest` option:
86 |
87 | ```
88 | bin/cake bootstrap install --latest
89 | ```
90 |
91 | 2. You will need to modify your `src/View/AppView` class to either extend `BootstrapUI\View\UIView` or
92 | use the trait `BootStrapUI\View\UIViewTrait`. For doing this you can either use the `modify_view` command, or
93 | [change your view manually](#appview-setup-using-uiview):
94 |
95 | ```
96 | bin/cake bootstrap modify_view
97 | ```
98 |
99 | This will rewrite your `src/View/AppView` like described in [AppView setup using UIView](#appview-setup-using-uiview).
100 |
101 | 3. BootstrapUI ships with some example layouts. You can install them using the `copy_layouts` command, or
102 | [copy them manually](#copying-example-layouts):
103 |
104 | ```
105 | bin/cake bootstrap copy_layouts
106 | ```
107 |
108 | This will copy the three example layouts `cover.php`, `dashboard.php` and `signin.php` to your application's
109 | `src/templates/layout/TwitterBootstrap`.
110 |
111 | ### Manual setup
112 |
113 | #### Installing Bootstrap assets via npm
114 |
115 | The [the `install` command](#using-the-bootstrap-commands) installs the Bootstrap assets via [npm], which you can also
116 | do manually if you wish to control which assets are being included, and where they are placed.
117 |
118 | Assuming you are in your application's root:
119 |
120 | ```
121 | npm install bootstrap@5 bootstrap-icons@1
122 | mkdir -p webroot/css
123 | mkdir -p webroot/font/fonts
124 | mkdir -p webroot/js
125 | cp node_modules/bootstrap/dist/css/bootstrap.css webroot/css/
126 | cp node_modules/bootstrap/dist/css/bootstrap.min.css webroot/css/
127 | cp node_modules/bootstrap/dist/js/bootstrap.bundle.js webroot/js/
128 | cp node_modules/bootstrap/dist/js/bootstrap.bundle.min.js webroot/js/
129 | cp node_modules/bootstrap-icons/font/bootstrap-icons.css webroot/font/
130 | cp node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff webroot/font/fonts/
131 | cp node_modules/bootstrap-icons/font/fonts/bootstrap-icons.woff2 webroot/font/fonts/
132 | cp vendor/friendsofcake/bootstrap-ui/webroot/font/bootstrap-icon-sizes.css webroot/font/
133 | ```
134 |
135 | #### AppView setup using UIView
136 |
137 | For a quick setup, just make your `AppView` class extend `BootstrapUI\View\UIView`. The base class will handle
138 | the initializing and loading of the BootstrapUI `default.php` layout for your app.
139 |
140 | The `src\View\AppView.php` will look something like the following:
141 |
142 | ```php
143 | declare(strict_types=1);
144 |
145 | namespace App\View;
146 |
147 | use BootstrapUI\View\UIView;
148 |
149 | class AppView extends UIView
150 | {
151 | /**
152 | * Initialization hook method.
153 | */
154 | public function initialize(): void
155 | {
156 | // Don't forget to call parent::initialize()
157 | parent::initialize();
158 | }
159 | }
160 | ```
161 |
162 | #### AppView setup using UIViewTrait
163 |
164 | If you're adding BootstrapUI to an existing application, it might be easier to use the trait, as it gives you more
165 | control over the loading of the layout.
166 |
167 | ```php
168 | declare(strict_types=1);
169 |
170 | namespace App\View;
171 |
172 | use BootstrapUI\View\UIViewTrait;
173 | use Cake\View\View;
174 |
175 | class AppView extends View
176 | {
177 | use UIViewTrait;
178 |
179 | /**
180 | * Initialization hook method.
181 | */
182 | public function initialize(): void
183 | {
184 | parent::initialize();
185 |
186 | // Call the initializeUI method from UIViewTrait
187 | $this->initializeUI();
188 | }
189 | }
190 | ```
191 |
192 | #### Copying example layouts
193 |
194 | In order to be able to use the BootstrapUI example layouts (directly taken from the Bootstrap examples), they need to be
195 | copied to your application's layouts directory, either by using
196 | [the `copy_layouts` command](#using-the-bootstrap-commands), or by copying the files manually:
197 |
198 | ```
199 | cp -R vendor/friendsofcake/bootstrap-ui/templates/layout/examples templates/layout/TwitterBootstrap
200 | ```
201 |
202 | ### BootstrapUI layouts
203 |
204 | BootstrapUI comes with its own `default.php` layout file and examples taken from the Bootstrap framework.
205 |
206 | When no layout for the view is defined, the `BootstrapUI\View\UIViewTrait` will load its own `default.php` layout file.
207 | You can override this behavior in two ways.
208 |
209 | - Assign a layout to the template with `$this->setLayout('layout')`.
210 | - Disable auto loading of the layout in `BootstrapUI\View\UIViewTrait` by adding `$this->initializeUI(['layout' => false]);` to your `AppView`'s `initialize()` function.
211 |
212 | #### Using the example layouts
213 |
214 | Once copied into your application's layouts directory (being it via
215 | [the `copy_layouts` command](#using-the-bootstrap-commands) or [manually](#copying-example-layouts)), you can simply
216 | extend the example layouts in your views like so:
217 |
218 | ```
219 | $this->extend('../layout/TwitterBootstrap/dashboard');
220 | ```
221 |
222 | Available types are:
223 |
224 | - `cover`
225 | - `signin`
226 | - `dashboard`
227 |
228 | **NOTE: Remember to set the stylesheets in the layouts you copy.**
229 |
230 | ### Including the Bootstrap framework
231 |
232 | If you are using [the BoostrapUI plugin's default layout](#bootstrapui-layouts), and you have installed the Bootstrap
233 | assets using [the `install` command](#using-the-bootstrap-commands), the required assets should automatically be
234 | included.
235 |
236 | If you wish to use your own layout template, then you need to take care of including the required CSS/JS files yourself.
237 |
238 | If you have installed the assets using [the `install` command](#using-the-bootstrap-commands), you can refer to
239 | them using the standard plugin syntax:
240 |
241 | ```php
242 | // in the
243 | echo $this->Html->css('BootstrapUI.bootstrap.min');
244 | echo $this->Html->css(['BootstrapUI./font/bootstrap-icons', 'BootstrapUI./font/bootstrap-icon-sizes']);
245 | echo $this->Html->script(['BootstrapUI.bootstrap.bundle.min']);
246 | ```
247 |
248 | If you have installed the assets manually, you'll need to use paths accordingly. With
249 | [the example copy commands](#installing-bootstrap-assets-via-npm) you could use the standard short path syntax:
250 |
251 | ```php
252 | echo $this->Html->css('bootstrap.min');
253 | echo $this->Html->css(['/font/bootstrap-icons', '/font/bootstrap-icon-sizes']);
254 | echo $this->Html->script(['bootstrap.bundle.min']);
255 | ```
256 |
257 | If you're using paths that don't adhere to the CakePHP conventions, you'll have to explicitly specify them:
258 |
259 | ```php
260 | echo $this->Html->css('/path/to/bootstrap.css');
261 | echo $this->Html->css(['/path/to/bootstrap-icons.css', '/path/to/bootstrap-icon-sizes.css']);
262 | echo $this->Html->script(['/path/to/bootstrap.bundle.js']);
263 | ```
264 |
265 | ## Bake templates
266 |
267 | For those of you who want even more automation, some bake templates have been included. Use them like so:
268 |
269 | ```
270 | bin/cake bake [subcommand] -t BootstrapUI
271 | ```
272 |
273 | Currently, bake templates for the following bake subcommands are included:
274 |
275 | ### `template`
276 |
277 | Additionally to the default `index`, `add`, `edit`, and `view` templates, a `login` template is available too. While
278 | the default CRUD action view templates can be utilized like this:
279 |
280 | ```bash
281 | bin/cake bake template ControllerName -t BootstrapUI
282 | ```
283 |
284 | the `login` template has to be used explicitly by specifying the action name:
285 |
286 | ```bash
287 | bin/cake bake template ControllerName login -t BootstrapUI
288 | ```
289 |
290 | ## Usage
291 |
292 | At the core of BootstrapUI is a collection of enhancements for CakePHP core helpers. Among other things, these helpers
293 | replace the HTML templates used to render elements for the views. This allows you to create forms and components that
294 | use the Bootstrap styles.
295 |
296 | The current list of enhanced helpers are:
297 |
298 | - `BootstrapUI\View\Helper\FlashHelper`
299 | - `BootstrapUI\View\Helper\FormHelper`
300 | - `BootstrapUI\View\Helper\HtmlHelper`
301 | - `BootstrapUI\View\Helper\PaginatorHelper`
302 | - `BootstrapUI\View\Helper\BreadcrumbsHelper`
303 |
304 | When the `BootstrapUI\View\UIViewTrait` is initialized it loads the above helpers with the same aliases as the
305 | CakePHP core helpers. That means that when you use `$this->Form->create()` in your views, the helper being used
306 | is from the BootstrapUI plugin.
307 |
308 | ### Basic forms
309 |
310 | ```php
311 | echo $this->Form->create($article);
312 | echo $this->Form->control('title');
313 | echo $this->Form->control('published', ['type' => 'checkbox']);
314 | echo $this->Form->button('Submit');
315 | echo $this->Form->end();
316 | ```
317 |
318 | will render this HTML:
319 |
320 | ```html
321 |
335 | ```
336 |
337 | ### Horizontal forms
338 |
339 | Horizontal forms automatically render labels and controls in separate columns (where applicable), labels in th first
340 | one, and controls in the second one.
341 |
342 | Alignment can be configured via the `align` option, which takes either a list of column sizes for the `md`
343 | [Bootstrap screen-size/breakpoint](https://getbootstrap.com/docs/5.3/layout/breakpoints/), or a matrix of
344 | screen-size/breakpoint names and column sizes.
345 |
346 | The following will use the default `md` screen-size/breakpoint:
347 |
348 | ```php
349 | use BootstrapUI\View\Helper\FormHelper;
350 |
351 | echo $this->Form->create($article, [
352 | 'align' => [
353 | FormHelper::GRID_COLUMN_ONE => 4, // first column (span over 4 columns)
354 | FormHelper::GRID_COLUMN_TWO => 8, // second column (span over 8 columns)
355 | ],
356 | ]);
357 | echo $this->Form->control('title');
358 | echo $this->Form->control('published', ['type' => 'checkbox']);
359 | echo $this->Form->submit();
360 | echo $this->Form->end();
361 | ```
362 |
363 | It will render this HTML:
364 |
365 | ```html
366 |
386 | ```
387 |
388 | The following uses a matrix of screen-sizes/breakpoints and column sizes:
389 |
390 | ```php
391 | use BootstrapUI\View\Helper\FormHelper;
392 |
393 | echo $this->Form->create($article, [
394 | 'align' => [
395 | // column sizes for the `sm` screen-size/breakpoint
396 | 'sm' => [
397 | FormHelper::GRID_COLUMN_ONE => 6,
398 | FormHelper::GRID_COLUMN_TWO => 6,
399 | ],
400 | // column sizes for the `md` screen-size/breakpoint
401 | 'md' => [
402 | FormHelper::GRID_COLUMN_ONE => 4,
403 | FormHelper::GRID_COLUMN_TWO => 8,
404 | ],
405 | ],
406 | ]);
407 | echo $this->Form->control('title');
408 | echo $this->Form->control('published', ['type' => 'checkbox']);
409 | echo $this->Form->button('Submit');
410 | echo $this->Form->end();
411 | ```
412 |
413 | It will render this HTML:
414 |
415 | ```html
416 |
436 | ```
437 |
438 | The default alignment will use the `md` screen-size/breakpoint and the following column sizes:
439 |
440 | ```php
441 | [
442 | FormHelper::GRID_COLUMN_ONE => 2,
443 | FormHelper::GRID_COLUMN_TWO => 10,
444 | ]
445 | ```
446 |
447 | ### Inline forms
448 |
449 | Inline forms will render controls on one and the same row, and hide labels for most controls.
450 |
451 | ```php
452 | echo $this->Form->create($article, [
453 | 'align' => 'inline',
454 | ]);
455 | echo $this->Form->control('title', ['placeholder' => 'Title']);
456 | echo $this->Form->control('published', ['type' => 'checkbox']);
457 | echo $this->Html->div('col-auto', $this->Form->button('Submit'));
458 | echo $this->Form->end();
459 | ```
460 |
461 | will render this HTML:
462 |
463 | ```html
464 |
484 | ```
485 |
486 | ### Spacing
487 |
488 | Out of the box BootstrapUI applies some default spacing for form controls. For default and horizontal aligned forms,
489 | the `mb-3` [spacing class](https://getbootstrap.com/docs/5.3/utilities/spacing/) is being applied to all controls,
490 | while inline forms are using the `g-3` [gutter class](https://getbootstrap.com/docs/5.3/layout/gutters/).
491 |
492 | This can be changed using the `spacing` option, it applies on a per-helper and per-form basis for all alignments, and
493 | for default/horizontal alignments it also applies on a per-control basis.
494 |
495 | ```php
496 | // for all forms
497 | echo $this->Form->setConfig([
498 | 'spacing' => 'mb-6',
499 | ]);
500 | ```
501 |
502 | ```php
503 | // for a specific form
504 | echo $this->Form->create($entity, [
505 | 'spacing' => 'mb-6',
506 | ]);
507 | ```
508 |
509 | ```php
510 | // for a specific control (default/horizontal aligned forms only)
511 | echo $this->Form->control('title', [
512 | 'spacing' => 'mb-6',
513 | ]);
514 | ```
515 |
516 | To completely disable this behavior, set the `spacing` option to `false`.
517 |
518 | ### Supported controls
519 |
520 | BootstrapUI supports and generates Bootstrap compatible markup for all of CakePHP's default controls. Additionally it
521 | explicitly supports Bootstrap specific markup for the following controls:
522 |
523 | - `color`
524 | - `range`
525 | - `switch`
526 |
527 | ### Container attributes
528 |
529 | Attributes of the outer control container can be changed via the `container` option, cutting the need to use custom
530 | templates for simple changes. The `class` attribute is a special case, its value will be prepended to the existing
531 | list of classes instead of replacing it.
532 |
533 | ```php
534 | echo $this->Form->control('title', [
535 | 'container' => [
536 | 'class' => 'my-title-control',
537 | 'data-meta' => 'meta information',
538 | ],
539 | ]);
540 | ```
541 |
542 | This would generate the following HTML:
543 |
544 | ```html
545 |
546 |
547 |
548 |
549 | ```
550 |
551 | ### Appending/Prepending content
552 |
553 | Appending/Prepending content to input groups is supported via the `append` and `prepend` options respectively.
554 |
555 | ```php
556 | echo $this->Form->control('email', [
557 | 'prepend' => '@',
558 | ]);
559 | ```
560 |
561 | This would generate the following HTML:
562 |
563 | ```html
564 |
565 |
566 |
567 | @
568 |
569 |
570 |
571 | ```
572 |
573 | #### Multiple addons
574 |
575 | Multiple addons can be defined as an array for the `append` and `prepend` options:
576 |
577 | ```php
578 | echo $this->Form->control('amount', [
579 | 'prepend' => ['$', '0.00'],
580 | ]);
581 | ```
582 |
583 | This would generate the following HTML:
584 |
585 | ```html
586 |
587 |
588 |
589 | $
590 | 0.00
591 |
592 |
593 |
594 | ```
595 |
596 | #### Addon options
597 |
598 | Addons support options that apply to the input group container. They can be defined by passing an array for the `append`
599 | and `prepend` options, and adding an array with options as the last entry.
600 |
601 | Options can contain HTML attributes as know from control options, as well as the special `size` option, which
602 | automatically translates to the corresponding input group size class.
603 |
604 | ```php
605 | echo $this->Form->control('amount', [
606 | 'prepend' => [
607 | '$',
608 | '0.00',
609 | [
610 | 'size' => 'lg',
611 | 'class' => 'custom',
612 | 'custom' => 'attribute',
613 | ],
614 | ],
615 | ]);
616 | ```
617 |
618 | This would generate the following HTML:
619 |
620 | ```html
621 |
622 |
623 |
624 | $
625 | 0.00
626 |
627 |
628 |
629 | ```
630 |
631 | ### Inline checkboxes and radio buttons
632 |
633 | [Inline checkboxes/switches and radio buttons](https://getbootstrap.com/docs/5.3/components/forms/#inline) (not to be
634 | confused with inline aligned forms), can be created by setting the `inline` option to `true`.
635 |
636 | Inlined checkboxes/switches and radio buttons will be rendered on the same horizontal row. When using horizontal form
637 | alignment however, only multi-checkboxes will render on the same row!
638 |
639 | ```php
640 | echo $this->Form->control('option_1', [
641 | 'type' => 'checkbox',
642 | 'inline' => true,
643 | ]);
644 | echo $this->Form->control('option_2', [
645 | 'type' => 'checkbox',
646 | 'inline' => true,
647 | ]);
648 | ```
649 |
650 | This would generate the following HTML:
651 |
652 | ```html
653 |
654 |
655 |
656 |
657 |
658 |
659 |
660 |
661 |
662 |
663 | ```
664 |
665 | ### Switches
666 |
667 | [Switch style checkboxes](https://getbootstrap.com/docs/5.3/forms/checks-radios/#switches) can be created by setting the
668 | `switch` option to `true`.
669 |
670 | ```php
671 | echo $this->Form->control('option', [
672 | 'type' => 'checkbox',
673 | 'switch' => true,
674 | ]);
675 | ```
676 |
677 | This would generate the following HTML:
678 |
679 | ```html
680 |
681 |
682 |
683 |
684 |
685 | ```
686 |
687 | ### Floating labels
688 |
689 | [Floating labels](https://getbootstrap.com/docs/5.3/forms/floating-labels) are supported for `text`, `textarea`, and
690 | (non-`multiple`) `select` controls. They can be enabled via the label's `floating` option:
691 |
692 | ```php
693 | echo $this->Form->control('title', [
694 | 'label' => [
695 | 'floating' => true,
696 | ],
697 | ]);
698 | ```
699 |
700 | This would generate the following HTML:
701 |
702 | ```html
703 |
704 |
705 |
706 |
707 | ```
708 |
709 | ### Help text
710 |
711 | Bootstrap's [form help text](https://getbootstrap.com/docs/5.3/components/forms/#help-text) is supported via the
712 | `help` option.
713 |
714 | The help text is by default being rendered in between of the control and the validation feedback.
715 |
716 | ```php
717 | echo $this->Form->control('title', [
718 | 'help' => 'Help text',
719 | ]);
720 | ```
721 |
722 | This would generate the following HTML:
723 |
724 | ```html
725 |
726 |
727 |
728 | Help text
729 |
730 | ```
731 |
732 | Attributes can be configured by passing an array for the `help` option, where the text is then defined in the `content`
733 | key:
734 |
735 | ```php
736 | echo $this->Form->control('title', [
737 | 'help' => [
738 | 'id' => 'custom-help',
739 | 'class' => 'custom',
740 | 'data-custom' => 'attribute',
741 | 'content' => 'Help text',
742 | ],
743 | ]);
744 | ```
745 |
746 | This would generate the following HTML:
747 |
748 | ```html
749 |
750 |
751 |
752 | Help text
753 |
754 | ```
755 |
756 | ### Tooltips
757 |
758 | [Bootstrap tooltips](https://getbootstrap.com/docs/5.3/components/tooltips/) can be added to labels via the `tooltip`
759 | option. The tooltip toggles are by default being rendered as a [Bootstrap icon](https://icons.getbootstrap.com/), which
760 | is being included by default when installing the assets via the `install` command.
761 |
762 | ```php
763 | echo $this->Form->control('title', [
764 | 'tooltip' => 'Tooltip text',
765 | ]);
766 | ```
767 |
768 | This would generate the following HTML:
769 |
770 | ```html
771 |
772 |
775 |
776 |
777 | ```
778 |
779 | If you want to use a different toggle, being it a different Boostrap icon, or maybe a completely different icon
780 | font/library, then you can do this by
781 | [overriding the `tooltip` template](https://book.cakephp.org/5/en/views/helpers/form.html#customizing-the-templates-formhelper-uses)
782 | accordingly, being it globally, per form, or per control:
783 |
784 | ```php
785 | echo $this->Form->control('title', [
786 | 'tooltip' => 'Tooltip text',
787 | 'templates' => [
788 | 'tooltip' => 'info',
789 | ],
790 | ]);
791 | ```
792 |
793 | ### Error feedback style
794 |
795 | BootstrapUI supports two styles of error feedback, the
796 | [regular Bootstrap text feedback](https://getbootstrap.com/docs/5.3/components/forms/#validation), and
797 | [Bootstrap tooltip feedback](https://getbootstrap.com/docs/5.3/components/forms/#tooltips) (not to be confused with
798 | label tooltips that are configured via the `tooltip` option!).
799 |
800 | The style can be configured via the `feedbackStyle` option, either globally, per form, or per control. The supported
801 | styles are:
802 |
803 | - `\BootstrapUI\View\Helper\FormHelper::FEEDBACK_STYLE_DEFAULT` Render error feedback as regular Bootstrap text
804 | feedback.
805 | - `\BootstrapUI\View\Helper\FormHelper::FEEDBACK_STYLE_TOOLTIP` Render error feedback as Bootstrap tooltip feedback
806 | (inline forms are using this style by default).
807 |
808 | Note that using the tooltip error style requires the form group elements to be non-static positioned! The form helper
809 | will automatically add Bootstraps [position utility class](https://getbootstrap.com/docs/5.3/utilities/position/)
810 | `position-relative` to the form group elements when the tooltip error style is enabled.
811 |
812 | If you need different positioning, use either CSS to override the `position` rule on the `.form-group` elements, or use
813 | the `formGroupPosition` option to set your desired position, either globally, per form, or per control. The option
814 | supports the following values:
815 |
816 | - `\BootstrapUI\View\Helper\FormHelper::POSITION_ABSOLUTE`
817 | - `\BootstrapUI\View\Helper\FormHelper::POSITION_FIXED`
818 | - `\BootstrapUI\View\Helper\FormHelper::POSITION_RELATIVE`
819 | - `\BootstrapUI\View\Helper\FormHelper::POSITION_STATIC`
820 | - `\BootstrapUI\View\Helper\FormHelper::POSITION_STICKY`
821 |
822 | ```php
823 | $this->Form->setConfig([
824 | 'feedbackStyle' => \BootstrapUI\View\Helper\FormHelper::FEEDBACK_STYLE_TOOLTIP,
825 | 'formGroupPosition' => \BootstrapUI\View\Helper\FormHelper::POSITION_ABSOLUTE,
826 | ]);
827 |
828 | // ...
829 |
830 | echo $this->Form->control('title');
831 | ```
832 |
833 | With an error on the `title` field, this would generate the following HTML:
834 |
835 | ```html
836 |
837 |
838 |
839 |
Error message
840 |
841 | ```
842 |
843 | ### Flash Messages / Alerts
844 |
845 | You can set Flash Messages using the default Flash component syntax. Supported types are `success`, `info`, `warning`,
846 | `error`.
847 |
848 | ```php
849 | $this->Flash->success('Your Success Message.');
850 | ```
851 |
852 | #### Alert styles
853 |
854 | If you need to set other Bootstrap Alert styles you can do this with:
855 |
856 | ```php
857 | $this->Flash->set('Your Dark Message.', ['params' => ['class' => 'dark']]);
858 | ```
859 |
860 | Supported styles are `primary`, `secondary`, `light`, `dark`.
861 |
862 | #### Icons
863 |
864 | By default alerts use Bootstrap icons depending on the alert type. The mapped types are `default`, `info`, `warning`,
865 | `error`, and `success`. You can disable/customize icons via the `icon` option/parameter, either globally for the flash
866 | helper, or individually for a single message.
867 |
868 | Message without icon:
869 |
870 | ```php
871 | $this->Flash->success('Message without icon.', [
872 | 'params' => [
873 | 'icon' => false,
874 | ],
875 | ]);
876 | ```
877 |
878 | Use a custom icon:
879 |
880 | ```php
881 | $this->Flash->success('Message with custom icon.', [
882 | 'params' => [
883 | 'icon' => 'mic-mute-fill',
884 | ],
885 | ]);
886 | ```
887 |
888 | Pass icon options (the icon name is optional here, when omitted, the default icon map will be looked up):
889 |
890 | ```php
891 | $this->Flash->success('Message with custom icon options.', [
892 | 'params' => [
893 | 'icon' => [
894 | 'name' => 'mic-mute-fill',
895 | 'size' => '2xl',
896 | 'class' => 'foo bar me-2',
897 | 'data-custom' => 'attribute',
898 | ],
899 | ],
900 | ]);
901 | ```
902 |
903 | ```html
904 |
905 | ```
906 |
907 | Use custom HTML:
908 |
909 | ```php
910 | $this->Flash->success('Message with custom icon HTML.', [
911 | 'params' => [
912 | 'icon' => 'volume_off',
913 | ],
914 | ]);
915 | ```
916 |
917 | Disable icons for all flash messages:
918 |
919 | ```php
920 | $this->loadHelper('Flash', [
921 | 'className' => 'BootstrapUI.Flash',
922 | 'icon' => false,
923 | ]);
924 | ```
925 |
926 | Set icon options for all flash messages (the default icon map will be used, and the options will be applied to all
927 | icons):
928 |
929 | ```php
930 | $this->loadHelper('Flash', [
931 | 'className' => 'BootstrapUI.Flash',
932 | 'icon' => [
933 | 'size' => '2xl',
934 | 'class' => 'foo bar me-2',
935 | 'data-custom' => 'attribute',
936 | ],
937 | ]);
938 | ```
939 |
940 | Define a custom icon map:
941 |
942 | ```php
943 | $this->loadHelper('Flash', [
944 | 'className' => 'BootstrapUI.Flash',
945 | 'iconMap' => [
946 | 'default' => 'info-circle-fill',
947 | 'success' => 'check-circle-fill',
948 | 'error' => 'exclamation-triangle-fill',
949 | 'info' => 'info-circle-fill',
950 | 'warning' => 'exclamation-triangle-fill',
951 | ],
952 | ]);
953 | ```
954 |
955 | Use a different icon set:
956 |
957 | ```php
958 | $this->Flash->success('Message with different icon set.', [
959 | 'params' => [
960 | 'icon' => [
961 | 'namespace' => 'fas',
962 | 'prefix' => 'fa',
963 | 'name' => 'microphone-slash',
964 | 'size' => '2xl',
965 | ],
966 | ],
967 | ]);
968 | ```
969 |
970 | ```html
971 |
972 | ```
973 |
974 | Use a different icon set for all flash messages:
975 |
976 | ```php
977 | $this->loadHelper('Html', [
978 | 'className' => 'BootstrapUI.Html',
979 | 'iconDefaults' => [
980 | 'namespace' => 'fas',
981 | 'prefix' => 'fa',
982 | ],
983 | ]);
984 | ```
985 |
986 | ```php
987 | $this->loadHelper('Flash', [
988 | 'className' => 'BootstrapUI.Flash',
989 | 'iconMap' => [
990 | 'default' => 'info-circle',
991 | 'success' => 'check-circle',
992 | 'error' => 'exclamation-triangle',
993 | 'info' => 'info-circle',
994 | 'warning' => 'exclamation-triangle',
995 | ],
996 | ]);
997 | ```
998 |
999 | ### Badges
1000 |
1001 | By default badges will render as `secondary` theme styled:
1002 |
1003 | ```php
1004 | echo $this->Html->badge('Text');
1005 | ```
1006 |
1007 | ```html
1008 | Text
1009 | ```
1010 |
1011 | #### Background colors
1012 |
1013 | [Background colors](https://getbootstrap.com/docs/5.3/components/badge/#background-colors) can be changed by specifying
1014 | one of the Bootstrap theme color names via the `class` option, the helper will make sure that the correct prefixes
1015 | are being applied:
1016 |
1017 | ```php
1018 | echo $this->Html->badge('Text', [
1019 | 'class' => 'danger',
1020 | ]);
1021 | ```
1022 |
1023 | ```html
1024 | Text
1025 | ```
1026 |
1027 | #### Using a different HTML tag
1028 |
1029 | By default badges are using the `` tag. This can be changed via the `tag` option:
1030 |
1031 | ```php
1032 | echo $this->Html->badge('Text', [
1033 | 'tag' => 'div',
1034 | ]);
1035 | ```
1036 |
1037 | ```html
1038 |
Text
1039 | ```
1040 |
1041 | ### Icons
1042 |
1043 | By default the HTML helper is configured to use [Bootstrap icons](https://icons.getbootstrap.com/).
1044 |
1045 | ```php
1046 | echo $this->Html->icon('mic-mute-fill');
1047 | ```
1048 |
1049 | ```html
1050 |
1051 | ```
1052 |
1053 | #### Sizes
1054 |
1055 | Sizes can be specified via the `size` option, the passed value will automatically be prefixed:
1056 |
1057 | ```php
1058 | echo $this->Html->icon('mic-mute-fill', [
1059 | 'size' => '2xl',
1060 | ]);
1061 | ```
1062 |
1063 | ```html
1064 |
1065 | ```
1066 |
1067 | This plugin ships Bootstrap icon classes for the following sizes that center-align the icon vertically: `2xs`, `xs`,
1068 | `sm`, `lg`, `xl`, and `2xl`, and the following ones that align the icons on the baseline: `1x`, `2x`, `3x`, `4x`, `5x`,
1069 | `6x`, `7x`, `8x`, `9x`, and `10x`.
1070 |
1071 | #### Using a different icon set
1072 |
1073 | You can use a different icon set by configuring the `namespace` and `prefix `options, either per `icon()` call:
1074 |
1075 | ```php
1076 | echo $this->Html->icon('microphone-slash', [
1077 | 'namespace' => 'fas',
1078 | 'prefix' => 'fa',
1079 | ]);
1080 | ```
1081 |
1082 | or globally for all usages of `HtmlHelper::icon()` by configuring the HTML helper defaults:
1083 |
1084 | ```php
1085 | $this->loadHelper('Html', [
1086 | 'className' => 'BootstrapUI.Html',
1087 | 'iconDefaults' => [
1088 | 'namespace' => 'fas',
1089 | 'prefix' => 'fa',
1090 | ],
1091 | ]);
1092 | ```
1093 |
1094 | ### Breadcrumbs
1095 |
1096 | The breadcrumbs helper is a drop-in replacement, no additional configuration is available/required.
1097 |
1098 | ```php
1099 | echo $this->Breadcrumbs
1100 | ->add('Home', '/')
1101 | ->add('Articles', '/articles')
1102 | ->add('View')
1103 | ->render();
1104 | ```
1105 |
1106 | ```html
1107 |
1114 | ```
1115 |
1116 | ### Pagination
1117 |
1118 | The paginator helper generates bootstrap compatible/styles markup when using the helper's standard methods, and also
1119 | includes a convenience method that can generate a full set of pagination controls, that is first/previous/next/last as
1120 | well as page number links, all enclosed in a list wrapper.
1121 |
1122 | ```php
1123 | echo $this->Paginator->first();
1124 | echo $this->Paginator->prev();
1125 | echo $this->Paginator->numbers();
1126 | echo $this->Paginator->next();
1127 | echo $this->Paginator->last();
1128 | ```
1129 |
1130 | This would generate the following HTML:
1131 |
1132 | ```html
1133 |
1199 | ```
1200 |
1201 | #### Generating a full set of controls
1202 |
1203 | A full set of pagination controls, that is first/previous/next/last as well as page number links, all enclosed in a list
1204 | wrapper, can be generated using the `links()` method.
1205 |
1206 | By default it renders numbers only:
1207 |
1208 | ```php
1209 | echo $this->Paginator->links();
1210 | ```
1211 |
1212 | This would generate the following HTML:
1213 |
1214 | ```html
1215 |
1226 | ```
1227 |
1228 | ##### Configuring controls
1229 |
1230 | The generated controls can be configured via the `first`, `prev`, `next`, and `last` options, which each can take either
1231 | boolean `true` to generate the control with the helper defaults, a string that is used as the control's text, or an
1232 | array that allows specifying the link text as well as the ARIA label.
1233 |
1234 | The generated controls can be configured via the `first`, `prev`, `next`, and `last` options, which each take either
1235 | boolean `true` to indicate that the control should be generated using the helper defaults, a string that is used as the
1236 | control's text, or an array with `label` and `text` options that determine the ARIA label value and the link text:
1237 |
1238 | ```php
1239 | echo $this->Paginator->links([
1240 | 'first' => '❮❮',
1241 | 'prev' => true,
1242 | 'next' => true,
1243 | 'last' => [
1244 | 'label' => 'End',
1245 | 'text' => '❯❯',
1246 | ],
1247 | ]);
1248 | ```
1249 |
1250 | This would generate the following HTML:
1251 |
1252 | ```html
1253 |
',
79 | ] + $this->_defaultConfig['templates'];
80 |
81 | parent::__construct($View, $config + [
82 | 'labels' => $this->_labels,
83 | ]);
84 | }
85 |
86 | /**
87 | * {@inheritDoc}
88 | *
89 | * This methods supports the following options additionally to the ones supported by the core:
90 | *
91 | * - `label` The text to use for the ARIA label property.
92 | * - `templates` An array of templates, or template file name containing the templates you'd like to use when
93 | * generating the link for first page. This method uses the `first` template.
94 | */
95 | public function first(string|int $first = '«', array $options = []): string
96 | {
97 | $options = $this->_templateOptions('first', $options);
98 |
99 | $templater = $this->templater();
100 | $templater->push();
101 | $templateMethod = is_string($options['templates']) ? 'load' : 'add';
102 | $templater->{$templateMethod}($options['templates']);
103 |
104 | $out = parent::first($first, $options);
105 |
106 | $templater->pop();
107 |
108 | return $out;
109 | }
110 |
111 | /**
112 | * {@inheritDoc}
113 | *
114 | * This methods supports the following options additionally to the ones supported by the core:
115 | *
116 | * - `label` The text to use for the ARIA label property.
117 | * - `templates` An array of templates, or template file name containing the templates you'd like to use when
118 | * generating the link for last page. This method uses the `last` template.
119 | */
120 | public function last(string|int $last = '»', array $options = []): string
121 | {
122 | $options = $this->_templateOptions('last', $options);
123 |
124 | $templater = $this->templater();
125 | $templater->push();
126 | $templateMethod = is_string($options['templates']) ? 'load' : 'add';
127 | $templater->{$templateMethod}($options['templates']);
128 |
129 | $out = parent::last($last, $options);
130 |
131 | $templater->pop();
132 |
133 | return $out;
134 | }
135 |
136 | /**
137 | * {@inheritDoc}
138 | *
139 | * This methods supports the following options additionally to the ones supported by the core:
140 | *
141 | * - `label` The text to use for the ARIA label property.
142 | */
143 | public function prev(string $title = '‹', array $options = []): string
144 | {
145 | $options = $this->_templateOptions('prev', $options);
146 |
147 | return parent::prev($title, $options);
148 | }
149 |
150 | /**
151 | * {@inheritDoc}
152 | *
153 | * This methods supports the following options additionally to the ones supported by the core:
154 | *
155 | * - `label` The text to use for the ARIA label property.
156 | */
157 | public function next(string $title = '›', array $options = []): string
158 | {
159 | $options = $this->_templateOptions('next', $options);
160 |
161 | return parent::next($title, $options);
162 | }
163 |
164 | /**
165 | * Returns a set of numbers for the paged result set, wrapped in a ul.
166 | *
167 | * In addition to the numbers, the method can also generate previous/next and first/last
168 | * links using additional options as shown below which are not available in
169 | * CakePHP core's PaginatorHelper::numbers(). It also wraps the numbers into a ul tag.
170 | *
171 | * ### Options
172 | *
173 | * - `first` If set generates "first" link. Can be `true`, a string, or an array.
174 | * - `prev` If set generates "previous" link. Can be `true`, a string, or an array.
175 | * - `next` If set generates "next" link. Can be `true`, a string, or an array.
176 | * - `last` If set generates "last" link. Can be `true`, a string, or an array.
177 | * - `size` Used to control sizing class added to UL tag. For eg.
178 | * using `'size' => 'lg'` would add class `pagination-lg` to UL tag.
179 | * - `escape` Whether to escape the link text. Defaults to `true`.
180 | *
181 | * @param array $options Options for the numbers.
182 | * @return string|false Pagination controls markup, or `false` in case of an invalid `size` option.
183 | * @link http://book.cakephp.org/3.0/en/views/helpers/paginator.html#creating-page-number-links
184 | */
185 | public function links(array $options = []): string|false
186 | {
187 | $class = 'pagination';
188 |
189 | $options += [
190 | 'class' => $class,
191 | 'after' => '',
192 | 'size' => null,
193 | 'escape' => true,
194 | ];
195 |
196 | $escape = $options['escape'];
197 | unset($options['escape']);
198 |
199 | $options['class'] = implode(' ', (array)$options['class']);
200 |
201 | if (!empty($options['size'])) {
202 | if (!in_array($options['size'], $this->_allowedSizes)) {
203 | return false;
204 | }
205 | $options['class'] .= " {$class}-{$options['size']}";
206 | }
207 |
208 | $options += [
209 | 'before' => '