├── .gitignore ├── composer.json ├── README.md └── src ├── BootstrapVerticalRenderer.php ├── BootstrapInlineRenderer.php └── BootstrapRenderer.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | .idaa 3 | .DS_Store 4 | composer.lock 5 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tomaj/nette-bootstrap-form", 3 | "description": "Nette bootstrap form renderer", 4 | "license": "LGPL-2.0-or-later", 5 | "keywords": ["nette", "form", "bootstrap", "renderer"], 6 | "authors": [ 7 | { 8 | "name": "Tomas Majer", 9 | "email": "tomasmajer@gmail.com", 10 | "homepage": "http://www.tomaj.sk/" 11 | } 12 | ], 13 | "require": { 14 | "php": ">= 7.1.0", 15 | "nette/forms": "^3.2" 16 | }, 17 | "autoload": { 18 | "classmap": [ 19 | "src/" 20 | ] 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Nette bootstrap form renderer 2 | ============================= 3 | 4 | Simple nette bootstrap form renderers. 5 | 6 | Installation 7 | ------------ 8 | 9 | ```sh 10 | composer require tomaj/nette-bootstrap-form 11 | ``` 12 | 13 | Usage 14 | ----- 15 | 16 | ```php 17 | use Tomaj\Form\Renderer\BootstrapRenderer; 18 | use Nette\Application\UI\Form; 19 | 20 | $form = new Form; 21 | $form->setRenderer(new BootstrapRenderer); 22 | ``` 23 | 24 | For inline form you can use ```Tomaj\Form\Renderer\BootstrapInlineRenderer``` 25 | 26 | For vertical form (bootstrap default) you can use ```Tomaj\Form\Renderer\BootstrapVerticalRenderer``` 27 | -------------------------------------------------------------------------------- /src/BootstrapVerticalRenderer.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'container' => null, 20 | ], 21 | 'error' => [ 22 | 'container' => 'div class="alert alert-danger"', 23 | 'item' => 'p', 24 | ], 25 | 'group' => [ 26 | 'container' => 'fieldset', 27 | 'label' => 'legend', 28 | 'description' => 'p', 29 | ], 30 | 'controls' => [ 31 | 'container' => null, 32 | ], 33 | 'pair' => [ 34 | 'container' => 'div class=form-group', 35 | '.required' => 'required', 36 | '.optional' => null, 37 | '.odd' => null, 38 | '.error' => 'has-error', 39 | ], 40 | 'control' => [ 41 | 'container' => '', 42 | '.odd' => null, 43 | 'description' => 'span class=help-block', 44 | 'requiredsuffix' => '', 45 | 'errorcontainer' => 'span class=help-block', 46 | 'erroritem' => '', 47 | '.required' => 'required', 48 | '.text' => 'text', 49 | '.password' => 'text', 50 | '.file' => 'text', 51 | '.submit' => 'button', 52 | '.image' => 'imagebutton', 53 | '.button' => 'button', 54 | ], 55 | 'label' => [ 56 | 'container' => '', 57 | 'suffix' => null, 58 | 'requiredsuffix' => '', 59 | ], 60 | 'hidden' => [ 61 | 'container' => 'div', 62 | ], 63 | ]; 64 | 65 | /** @var bool */ 66 | private $novalidate; 67 | 68 | public function __construct(bool $novalidate = true) 69 | { 70 | $this->novalidate = $novalidate; 71 | } 72 | 73 | public function render(Form $form, string $mode = null): string 74 | { 75 | if ($this->novalidate) { 76 | $form->getElementPrototype()->setNovalidate('novalidate'); 77 | } 78 | 79 | $usedPrimary = false; 80 | foreach ($form->getControls() as $control) { 81 | if ($control instanceof Button) { 82 | if (strpos($control->getControlPrototype()->getClass() ?? '', 'btn') === false) { 83 | $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-default'); 84 | $usedPrimary = true; 85 | } 86 | } elseif ($control instanceof TextBase || 87 | $control instanceof SelectBox || 88 | $control instanceof MultiSelectBox) { 89 | $control->getControlPrototype()->addClass('form-control'); 90 | } elseif ($control instanceof Checkbox || 91 | $control instanceof CheckboxList || 92 | $control instanceof RadioList) { 93 | $control->getSeparatorPrototype()->setName('div')->addClass($control->getControlPrototype()->type); 94 | } 95 | } 96 | 97 | return parent::render($form, $mode); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/BootstrapInlineRenderer.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'container' => '', 20 | ], 21 | 'error' => [ 22 | 'container' => 'div class="alert alert-danger"', 23 | 'item' => 'p', 24 | ], 25 | 'group' => [ 26 | 'container' => 'fieldset', 27 | 'label' => 'legend', 28 | 'description' => 'p', 29 | ], 30 | 'controls' => [ 31 | 'container' => '', 32 | ], 33 | 'pair' => [ 34 | 'container' => 'div class=form-group', 35 | '.required' => 'required', 36 | '.optional' => null, 37 | '.odd' => null, 38 | '.error' => 'has-error', 39 | ], 40 | 'control' => [ 41 | 'container' => null, 42 | '.odd' => null, 43 | 'description' => 'span class=help-block', 44 | 'requiredsuffix' => '', 45 | 'errorcontainer' => 'span class=help-block', 46 | 'erroritem' => '', 47 | '.required' => 'required', 48 | '.text' => 'text', 49 | '.password' => 'text', 50 | '.file' => 'text', 51 | '.submit' => 'button', 52 | '.image' => 'imagebutton', 53 | '.button' => 'button', 54 | ], 55 | 'label' => [ 56 | 'container' => '', 57 | 'suffix' => null, 58 | 'requiredsuffix' => '', 59 | ], 60 | 'hidden' => [ 61 | 'container' => 'div', 62 | ], 63 | ]; 64 | 65 | /** @var bool */ 66 | private $novalidate; 67 | 68 | public function __construct(bool $novalidate = true) 69 | { 70 | $this->novalidate = $novalidate; 71 | } 72 | 73 | public function render(Form $form, string $mode = null): string 74 | { 75 | $form->getElementPrototype()->addClass('form-inline'); 76 | 77 | if ($this->novalidate) { 78 | $form->getElementPrototype()->setNovalidate('novalidate'); 79 | } 80 | 81 | foreach ($form->getControls() as $control) { 82 | if ($control instanceof Button) { 83 | if (strpos($control->getControlPrototype()->getClass() ?? '', 'btn') === false) { 84 | $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-default'); 85 | $usedPrimary = true; 86 | } 87 | } elseif ($control instanceof TextBase || 88 | $control instanceof SelectBox || 89 | $control instanceof MultiSelectBox) { 90 | $control->getControlPrototype()->addClass('form-control'); 91 | } elseif ($control instanceof Checkbox || 92 | $control instanceof CheckboxList || 93 | $control instanceof RadioList) { 94 | $control->getSeparatorPrototype()->setName('div')->addClass($control->getControlPrototype()->type); 95 | } 96 | } 97 | 98 | return parent::render($form, $mode); 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/BootstrapRenderer.php: -------------------------------------------------------------------------------- 1 | [ 19 | 'container' => null, 20 | ], 21 | 'error' => [ 22 | 'container' => 'div class="alert alert-danger"', 23 | 'item' => 'p', 24 | ], 25 | 'group' => [ 26 | 'container' => 'fieldset', 27 | 'label' => 'legend', 28 | 'description' => 'p', 29 | ], 30 | 'controls' => [ 31 | 'container' => 'div', 32 | ], 33 | 'pair' => [ 34 | 'container' => 'div class=form-group', 35 | '.required' => 'required', 36 | '.optional' => null, 37 | '.odd' => null, 38 | '.error' => 'has-error', 39 | ], 40 | 'control' => [ 41 | 'container' => 'div class=col-sm-9', 42 | '.odd' => null, 43 | 'description' => 'span class=help-block', 44 | 'requiredsuffix' => '', 45 | 'errorcontainer' => 'span class=help-block', 46 | 'erroritem' => '', 47 | '.required' => 'required', 48 | '.text' => 'text', 49 | '.password' => 'text', 50 | '.file' => 'text', 51 | '.submit' => 'button', 52 | '.image' => 'imagebutton', 53 | '.button' => 'button', 54 | ], 55 | 'label' => [ 56 | 'container' => 'div class="col-sm-3 control-label"', 57 | 'suffix' => null, 58 | 'requiredsuffix' => '', 59 | ], 60 | 'hidden' => [ 61 | 'container' => 'div', 62 | ], 63 | ]; 64 | 65 | /** @var bool */ 66 | private $novalidate; 67 | 68 | public function __construct(bool $novalidate = true) 69 | { 70 | $this->novalidate = $novalidate; 71 | } 72 | 73 | public function render(Form $form, string $mode = null): string 74 | { 75 | $form->getElementPrototype()->addClass('form-horizontal'); 76 | 77 | if ($this->novalidate) { 78 | $form->getElementPrototype()->setNovalidate('novalidate'); 79 | } 80 | 81 | foreach ($form->getControls() as $control) { 82 | if ($control instanceof Button) { 83 | if (strpos($control->getControlPrototype()->getClass() ?? '', 'btn') === false) { 84 | $control->getControlPrototype()->addClass(empty($usedPrimary) ? 'btn btn-primary' : 'btn btn-default'); 85 | $usedPrimary = true; 86 | } 87 | } elseif ($control instanceof TextBase || 88 | $control instanceof SelectBox || 89 | $control instanceof MultiSelectBox) { 90 | $control->getControlPrototype()->addClass('form-control'); 91 | } elseif ($control instanceof Checkbox || 92 | $control instanceof CheckboxList || 93 | $control instanceof RadioList) { 94 | $control->getSeparatorPrototype()->setName('div')->addClass($control->getControlPrototype()->type); 95 | } 96 | } 97 | 98 | return parent::render($form, $mode); 99 | } 100 | } 101 | --------------------------------------------------------------------------------