Skip to content

Commit d71fa5a

Browse files
MartinMystikJonasf3l1x
authored andcommitted
Customizable column widths for horizontal Bootstrap forms
1 parent fd8627c commit d71fa5a

22 files changed

+221
-87
lines changed
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Contributte\Forms\Rendering;
4+
5+
use Nette\Forms\Rendering\DefaultFormRenderer;
6+
7+
class AbstractBootstrapHorizontalRenderer extends DefaultFormRenderer
8+
{
9+
10+
/** @var int */
11+
protected $colsLabel = 3;
12+
13+
/** @var int */
14+
protected $colsControl = 9;
15+
16+
public function setColumns(int $colsLabel, int $colsControl): void
17+
{
18+
$this->colsLabel = $colsLabel;
19+
$this->colsControl = $colsControl;
20+
}
21+
22+
protected function getValue(string $name)
23+
{
24+
$value = parent::getValue($name);
25+
if (is_string($value)) {
26+
$value = $this->replacePlaceholders($value);
27+
}
28+
29+
return $value;
30+
}
31+
32+
protected function replacePlaceholders(string $value): string
33+
{
34+
$value = str_replace('%colsLabel%', (string) $this->colsLabel, $value);
35+
$value = str_replace('%colsControl%', (string) $this->colsControl, $value);
36+
return $value;
37+
}
38+
39+
}

src/Rendering/Bootstrap3HorizontalRenderer.php

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,8 @@
44

55
use Nette\Forms\Controls;
66
use Nette\Forms\Form;
7-
use Nette\Forms\Rendering\DefaultFormRenderer;
87

9-
class Bootstrap3HorizontalRenderer extends DefaultFormRenderer
8+
class Bootstrap3HorizontalRenderer extends AbstractBootstrapHorizontalRenderer
109
{
1110

1211
/** @var mixed[] */
@@ -34,7 +33,7 @@ class Bootstrap3HorizontalRenderer extends DefaultFormRenderer
3433
'.error' => 'has-error',
3534
],
3635
'control' => [
37-
'container' => 'div class=col-sm-9',
36+
'container' => 'div class=col-sm-%colsControl%',
3837
'.odd' => null,
3938
'description' => 'span class=help-block',
4039
'requiredsuffix' => '',
@@ -49,7 +48,7 @@ class Bootstrap3HorizontalRenderer extends DefaultFormRenderer
4948
'.button' => 'button',
5049
],
5150
'label' => [
52-
'container' => 'div class="col-sm-3 control-label"',
51+
'container' => 'div class="col-sm-%colsLabel% control-label"',
5352
'suffix' => null,
5453
'requiredsuffix' => '',
5554
],
@@ -75,9 +74,7 @@ public function render(Form $form, $mode = null): string
7574
foreach ($form->getControls() as $control) {
7675
switch (true) {
7776
case $control instanceof Controls\Button:
78-
/** @var string|null $class */
79-
$class = $control->getControlPrototype()->getAttribute('class');
80-
if ($class === null || mb_strpos($class, 'btn') === false) {
77+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
8178
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-default');
8279
$usedPrimary = true;
8380
}

src/Rendering/Bootstrap3InlineRenderer.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ public function render(Form $form, $mode = null): string
7373
foreach ($form->getControls() as $control) {
7474
switch (true) {
7575
case $control instanceof Controls\Button:
76-
/** @var string|null $class */
77-
$class = $control->getControlPrototype()->getAttribute('class');
78-
if ($class === null || mb_strpos($class, 'btn') === false) {
76+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
7977
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-default');
8078
$usedPrimary = true;
8179
}

src/Rendering/Bootstrap3VerticalRenderer.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,7 @@ public function render(Form $form, $mode = null): string
7373
foreach ($form->getControls() as $control) {
7474
switch (true) {
7575
case $control instanceof Controls\Button:
76-
/** @var string|null $class */
77-
$class = $control->getControlPrototype()->getAttribute('class');
78-
if ($class === null || mb_strpos($class, 'btn') === false) {
76+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
7977
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-default');
8078
$usedPrimary = true;
8179
}

src/Rendering/Bootstrap4HorizontalRenderer.php

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
use Nette\Forms\Controls;
66
use Nette\Forms\Form;
77
use Nette\Forms\IControl;
8-
use Nette\Forms\Rendering\DefaultFormRenderer;
98
use Nette\Utils\Html;
109

11-
class Bootstrap4HorizontalRenderer extends DefaultFormRenderer
10+
class Bootstrap4HorizontalRenderer extends AbstractBootstrapHorizontalRenderer
1211
{
1312

1413
/** @var mixed[] */
@@ -35,7 +34,7 @@ class Bootstrap4HorizontalRenderer extends DefaultFormRenderer
3534
'.odd' => null,
3635
],
3736
'control' => [
38-
'container' => 'div class="col col-sm-9"',
37+
'container' => 'div class="col col-sm-%colsControl%"',
3938
'.odd' => null,
4039
'description' => 'span class="form-text"',
4140
'requiredsuffix' => '',
@@ -76,14 +75,12 @@ public function render(Form $form, $mode = null): string
7675
&& !($control instanceof Controls\Checkbox)
7776
&& !($control instanceof Controls\CheckboxList)
7877
&& !($control instanceof Controls\RadioList)) {
79-
$control->getLabelPrototype()->addClass('col-form-label col col-sm-3');
78+
$control->getLabelPrototype()->addClass($this->replacePlaceholders('col-form-label col col-sm-%colsLabel%'));
8079
}
8180

8281
switch (true) {
8382
case $control instanceof Controls\Button:
84-
/** @var string|null $class */
85-
$class = $control->getControlPrototype()->getAttribute('class');
86-
if ($class === null || mb_strpos($class, 'btn') === false) {
83+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
8784
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-secondary');
8885
$usedPrimary = true;
8986
}
@@ -111,7 +108,7 @@ public function renderLabel(IControl $control): Html
111108
{
112109
$label = parent::renderLabel($control);
113110
if ($control instanceof Controls\Checkbox || $control instanceof Controls\CheckboxList || $control instanceof Controls\RadioList) {
114-
$label->addHtml('<div class="col col-sm-3"></div>');
111+
$label->addHtml($this->replacePlaceholders('<div class="col col-sm-%colsLabel%"></div>'));
115112
}
116113

117114
return $label;

src/Rendering/Bootstrap4InlineRenderer.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ public function render(Form $form, $mode = null): string
7676

7777
switch (true) {
7878
case $control instanceof Controls\Button:
79-
/** @var string|null $class */
80-
$class = $control->getControlPrototype()->getAttribute('class');
81-
if ($class === null || mb_strpos($class, 'btn') === false) {
79+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
8280
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-secondary');
8381
$usedPrimary = true;
8482
}

src/Rendering/Bootstrap4VerticalRenderer.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,7 @@ public function render(Form $form, $mode = null): string
7676

7777
switch (true) {
7878
case $control instanceof Controls\Button:
79-
/** @var string|null $class */
80-
$class = $control->getControlPrototype()->getAttribute('class');
81-
if ($class === null || mb_strpos($class, 'btn') === false) {
79+
if (!Helpers::htmlClassContains($control->getControlPrototype(), 'btn')) {
8280
$control->getControlPrototype()->addClass($usedPrimary === false ? 'btn btn-primary' : 'btn btn-secondary');
8381
$usedPrimary = true;
8482
}

src/Rendering/Helpers.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace Contributte\Forms\Rendering;
4+
5+
use Nette\Utils\Html;
6+
7+
class Helpers
8+
{
9+
10+
public static function htmlClassContains(Html $html, string $contains): bool
11+
{
12+
/** @var string|string[]|null $class */
13+
$class = $html->getAttribute('class');
14+
if (is_array($class)) {
15+
$class = implode(' ', array_keys($class));
16+
}
17+
18+
return $class !== null && mb_strpos($class, $contains) !== false;
19+
}
20+
21+
}

tests/cases/Rendering/Bootstrap3HorizontalRenderer.phpt

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,25 @@ use Tester\Assert;
1010

1111
require_once __DIR__ . '/../../bootstrap.php';
1212

13-
$form = new Form();
14-
$form->addText('text1', 'Text 1');
15-
$form->addText('text2', 'Text 2');
16-
$form->addSelect('select', 'Select', ['1' => 'Option 1', '2' => 'Option 2']);
17-
$form->addCheckbox('checkbox', 'Checkbox');
18-
$form->addSubmit('button', 'Button');
19-
20-
test(function () use ($form): void {
13+
test(function (): void {
14+
$form = new Form();
15+
$form->addText('text1', 'Text 1');
16+
$form->addText('text2', 'Text 2')->setHtmlAttribute('class', 'my-text');
17+
$form->addSelect('select', 'Select', ['1' => 'Option 1', '2' => 'Option 2']);
18+
$form->addCheckbox('checkbox', 'Checkbox');
19+
$form->addSubmit('button', 'Button')->setHtmlAttribute('class', 'my-button');
2120
$renderer = new Bootstrap3HorizontalRenderer();
2221
Assert::matchFile(__DIR__ . '/expected/bootstrap3horizontal.html', $renderer->render($form));
2322
});
23+
24+
test(function (): void {
25+
$form = new Form();
26+
$form->addText('text1', 'Text 1');
27+
$form->addText('text2', 'Text 2')->setHtmlAttribute('class', 'my-text');
28+
$form->addSelect('select', 'Select', ['1' => 'Option 1', '2' => 'Option 2']);
29+
$form->addCheckbox('checkbox', 'Checkbox');
30+
$form->addSubmit('button', 'Button')->setHtmlAttribute('class', 'my-button');
31+
$renderer = new Bootstrap3HorizontalRenderer();
32+
$renderer->setColumns(2, 10);
33+
Assert::matchFile(__DIR__ . '/expected/bootstrap3horizontal.cols.html', $renderer->render($form));
34+
});

tests/cases/Rendering/Bootstrap3InlineRenderer.phpt

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,13 @@ use Tester\Assert;
1010

1111
require_once __DIR__ . '/../../bootstrap.php';
1212

13-
$form = new Form();
14-
$form->addText('text1', 'Text 1');
15-
$form->addText('text2', 'Text 2');
16-
$form->addSelect('select', 'Select', ['1' => 'Option 1', '2' => 'Option 2']);
17-
$form->addCheckbox('checkbox', 'Checkbox');
18-
$form->addSubmit('button', 'Button');
19-
20-
test(function () use ($form): void {
13+
test(function (): void {
14+
$form = new Form();
15+
$form->addText('text1', 'Text 1');
16+
$form->addText('text2', 'Text 2')->setHtmlAttribute('class', 'my-text');
17+
$form->addSelect('select', 'Select', ['1' => 'Option 1', '2' => 'Option 2']);
18+
$form->addCheckbox('checkbox', 'Checkbox');
19+
$form->addSubmit('button', 'Button')->setHtmlAttribute('class', 'my-button');
2120
$renderer = new Bootstrap3InlineRenderer();
2221
Assert::matchFile(__DIR__ . '/expected/bootstrap3inline.html', $renderer->render($form));
2322
});

0 commit comments

Comments
 (0)