From 7f40f132718b40a98d4c803d844e898660b9f6b3 Mon Sep 17 00:00:00 2001 From: Sergei Predvoditelev Date: Sun, 27 Oct 2024 16:37:09 +0300 Subject: [PATCH] Add ability to wrap items in checkbox and radio lists (#227) --- CHANGELOG.md | 2 ++ src/Widget/CheckboxList/CheckboxList.php | 28 +++++++++++++++++++++++- src/Widget/RadioList/RadioList.php | 28 +++++++++++++++++++++++- tests/Widget/CheckboxListTest.php | 25 +++++++++++++++++++++ tests/Widget/RadioListTest.php | 25 +++++++++++++++++++++ 5 files changed, 106 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8042d7..93b4c1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ - New #224: Add optional `wrap` parameter to `BooleanInputTag::label()` method that controls whether to wrap input tag with label tag or place them aside (@vjik) - New #225: Add `CheckboxList::checkboxLabelWrap()` and `RadioList::radioLabelWrap()` methods (@vjik) +- New #227: Add ability to wrap items in checkbox and radio lists by methods `CheckboxList::checkboxWrapTag()`, + `CheckboxList::checkboxWrapAttributes()`, `RadioList::radioWrapTag()` and `RadioList::radioWrapAttributes()` (@vjik) ## 3.7.0 September 18, 2024 diff --git a/src/Widget/CheckboxList/CheckboxList.php b/src/Widget/CheckboxList/CheckboxList.php index fa8e625..76103fc 100644 --- a/src/Widget/CheckboxList/CheckboxList.php +++ b/src/Widget/CheckboxList/CheckboxList.php @@ -21,6 +21,10 @@ final class CheckboxList implements NoEncodeStringableInterface { private ?string $containerTag = 'div'; private array $containerAttributes = []; + + private ?string $checkboxWrapTag = null; + private array $checkboxWrapAttributes = []; + private array $checkboxAttributes = []; private array $checkboxLabelAttributes = []; private bool $checkboxLabelWrap = true; @@ -87,6 +91,20 @@ public function containerAttributes(array $attributes): self return $new; } + public function checkboxWrapTag(?string $name): self + { + $new = clone $this; + $new->checkboxWrapTag = $name; + return $new; + } + + public function checkboxWrapAttributes(array $attributes): self + { + $new = clone $this; + $new->checkboxWrapAttributes = $attributes; + return $new; + } + public function addCheckboxAttributes(array $attributes): self { $new = clone $this; @@ -247,6 +265,14 @@ public function render(): string { $name = Html::getArrayableName($this->name); + if ($this->checkboxWrapTag === null) { + $beforeCheckbox = ''; + $afterCheckbox = ''; + } else { + $beforeCheckbox = Html::openTag($this->checkboxWrapTag, $this->checkboxWrapAttributes) . "\n"; + $afterCheckbox = "\n" . Html::closeTag($this->checkboxWrapTag); + } + $lines = []; $index = 0; foreach ($this->items as $value => $label) { @@ -265,7 +291,7 @@ public function render(): string $this->checkboxLabelAttributes, $this->checkboxLabelWrap, ); - $lines[] = $this->formatItem($item); + $lines[] = $beforeCheckbox . $this->formatItem($item) . $afterCheckbox; $index++; } diff --git a/src/Widget/RadioList/RadioList.php b/src/Widget/RadioList/RadioList.php index 18709a4..4dbb576 100644 --- a/src/Widget/RadioList/RadioList.php +++ b/src/Widget/RadioList/RadioList.php @@ -18,6 +18,10 @@ final class RadioList implements NoEncodeStringableInterface { private ?string $containerTag = 'div'; private array $containerAttributes = []; + + private ?string $radioWrapTag = null; + private array $radioWrapAttributes = []; + private array $radioAttributes = []; private array $radioLabelAttributes = []; private bool $radioLabelWrap = true; @@ -81,6 +85,20 @@ public function containerAttributes(array $attributes): self return $new; } + public function radioWrapTag(?string $name): self + { + $new = clone $this; + $new->radioWrapTag = $name; + return $new; + } + + public function radioWrapAttributes(array $attributes): self + { + $new = clone $this; + $new->radioWrapAttributes = $attributes; + return $new; + } + public function addRadioAttributes(array $attributes): self { $new = clone $this; @@ -229,6 +247,14 @@ public function itemFormatter(?Closure $formatter): self public function render(): string { + if ($this->radioWrapTag === null) { + $beforeRadio = ''; + $afterRadio = ''; + } else { + $beforeRadio = Html::openTag($this->radioWrapTag, $this->radioWrapAttributes) . "\n"; + $afterRadio = "\n" . Html::closeTag($this->radioWrapTag); + } + $lines = []; $index = 0; foreach ($this->items as $value => $label) { @@ -247,7 +273,7 @@ public function render(): string $this->radioLabelAttributes, $this->radioLabelWrap, ); - $lines[] = $this->formatItem($item); + $lines[] = $beforeRadio . $this->formatItem($item) . $afterRadio; $index++; } diff --git a/tests/Widget/CheckboxListTest.php b/tests/Widget/CheckboxListTest.php index 729d5b3..9c750fe 100644 --- a/tests/Widget/CheckboxListTest.php +++ b/tests/Widget/CheckboxListTest.php @@ -758,6 +758,29 @@ public function testDisableCheckboxLabelWrap(): void ); } + public function testCheckboxWrap(): void + { + $html = CheckboxList::create('test') + ->items([1 => 'One', 2 => 'Two']) + ->checkboxWrapTag('div') + ->checkboxWrapAttributes(['class' => 'form-check']) + ->render(); + + $this->assertSame( + << +
+ +
+
+ +
+ + HTML, + $html, + ); + } + public function testStringable(): void { $this->assertSame( @@ -773,6 +796,8 @@ public function testImmutability(): void $this->assertNotSame($widget, $widget->withoutContainer()); $this->assertNotSame($widget, $widget->containerTag('')); $this->assertNotSame($widget, $widget->containerAttributes([])); + $this->assertNotSame($widget, $widget->checkboxWrapTag('div')); + $this->assertNotSame($widget, $widget->checkboxWrapAttributes([])); $this->assertNotSame($widget, $widget->addCheckboxAttributes([])); $this->assertNotSame($widget, $widget->checkboxAttributes([])); $this->assertNotSame($widget, $widget->addCheckboxLabelAttributes([])); diff --git a/tests/Widget/RadioListTest.php b/tests/Widget/RadioListTest.php index b21d83c..763b438 100644 --- a/tests/Widget/RadioListTest.php +++ b/tests/Widget/RadioListTest.php @@ -708,6 +708,29 @@ public function testDisableRadioLabelWrap(): void ); } + public function testRadioWrap(): void + { + $html = RadioList::create('test') + ->items([1 => 'One', 2 => 'Two']) + ->radioWrapTag('div') + ->radioWrapAttributes(['class' => 'form-check']) + ->render(); + + $this->assertSame( + << +
+ +
+
+ +
+ + HTML, + $html, + ); + } + public function testStringable(): void { $this->assertSame( @@ -723,6 +746,8 @@ public function testImmutability(): void $this->assertNotSame($widget, $widget->withoutContainer()); $this->assertNotSame($widget, $widget->containerTag('')); $this->assertNotSame($widget, $widget->containerAttributes([])); + $this->assertNotSame($widget, $widget->radioWrapTag('div')); + $this->assertNotSame($widget, $widget->radioWrapAttributes([])); $this->assertNotSame($widget, $widget->addRadioAttributes([])); $this->assertNotSame($widget, $widget->radioAttributes([])); $this->assertNotSame($widget, $widget->radioLabelWrap(false));