Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 4.1.1 under development

- New #277: Add `beforeCheckbox()` and `afterCheckbox()` methods to `CheckboxList`, and `beforeRadio()` and
`afterRadio()` methods to `RadioList` (@vjik)
- New #276: Add `beforeInput()` and `afterInput()` methods to abstract `BooleanInputTag`, extended by `Radio`
and `Checkbox` (@vjik)

Expand Down
26 changes: 25 additions & 1 deletion src/Widget/CheckboxList/CheckboxList.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ final class CheckboxList implements NoEncodeStringableInterface
private array $checkboxAttributes = [];
private array $checkboxLabelAttributes = [];
private bool $checkboxLabelWrap = true;
private string|Stringable $beforeCheckbox = '';
private string|Stringable $afterCheckbox = '';

/**
* @var array[]
Expand Down Expand Up @@ -164,6 +166,26 @@ public function checkboxLabelWrap(bool $wrap): self
return $new;
}

/**
* @param string|Stringable $content Content to be rendered before each checkbox input.
*/
public function beforeCheckbox(string|Stringable $content): self
{
$new = clone $this;
$new->beforeCheckbox = $content;
return $new;
}

/**
* @param string|Stringable $content Content to be rendered after each checkbox input.
*/
public function afterCheckbox(string|Stringable $content): self
{
$new = clone $this;
$new->afterCheckbox = $content;
return $new;
}

/**
* @param array[] $attributes
*/
Expand Down Expand Up @@ -365,7 +387,9 @@ private function formatItem(CheckboxItem $item): string
$checkbox = Html::checkbox($item->name, $item->value, $item->checkboxAttributes)
->checked($item->checked)
->label($item->label, $item->labelAttributes, $item->labelWrap)
->labelEncode($item->encodeLabel);
->labelEncode($item->encodeLabel)
->beforeInput($this->beforeCheckbox)
->afterInput($this->afterCheckbox);

return $checkbox->render();
}
Expand Down
26 changes: 25 additions & 1 deletion src/Widget/RadioList/RadioList.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ final class RadioList implements NoEncodeStringableInterface
private array $radioAttributes = [];
private array $radioLabelAttributes = [];
private bool $radioLabelWrap = true;
private string|Stringable $beforeRadio = '';
private string|Stringable $afterRadio = '';

/**
* @var array[]
Expand Down Expand Up @@ -155,6 +157,26 @@ public function radioLabelWrap(bool $wrap): self
return $new;
}

/**
* @param string|Stringable $content Content to be rendered before each radio input.
*/
public function beforeRadio(string|Stringable $content): self
{
$new = clone $this;
$new->beforeRadio = $content;
return $new;
}

/**
* @param string|Stringable $content Content to be rendered after each radio input.
*/
public function afterRadio(string|Stringable $content): self
{
$new = clone $this;
$new->afterRadio = $content;
return $new;
}

/**
* @param array[] $attributes
*/
Expand Down Expand Up @@ -344,7 +366,9 @@ private function formatItem(RadioItem $item): string
$radio = Html::radio($item->name, $item->value, $item->radioAttributes)
->checked($item->checked)
->label($item->label, $item->labelAttributes, $item->labelWrap)
->labelEncode($item->encodeLabel);
->labelEncode($item->encodeLabel)
->beforeInput($this->beforeRadio)
->afterInput($this->afterRadio);

return $radio->render();
}
Expand Down
44 changes: 44 additions & 0 deletions tests/Widget/CheckboxListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
use ArrayObject;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Stringable;
use Yiisoft\Html\Html;
use Yiisoft\Html\Tests\Objects\IterableObject;
use Yiisoft\Html\Tests\Objects\StringableObject;
use Yiisoft\Html\Tests\Support\IntegerEnum;
use Yiisoft\Html\Tests\Support\StringEnum;
use Yiisoft\Html\Widget\CheckboxList\CheckboxList;
Expand Down Expand Up @@ -194,6 +196,46 @@ public function testCheckboxLabelAttributesMerge(): void
);
}

public static function dataBeforeCheckbox(): iterable
{
yield ['<b>*</b>', '<b>*</b>'];
yield ['<b>*</b>', new StringableObject('<b>*</b>')];
}

#[DataProvider('dataBeforeCheckbox')]
public function testBeforeCheckbox(string $expected, string|Stringable $content): void
{
$this->assertSame(
'<label>' . $expected . '<input name="test[]" value="1" type="checkbox"> One</label>' . "\n"
. '<label>' . $expected . '<input name="test[]" value="2" type="checkbox"> Two</label>',
(new CheckboxList('test'))
->items([1 => 'One', 2 => 'Two'])
->beforeCheckbox($content)
->withoutContainer()
->render(),
);
}

public static function dataAfterCheckbox(): iterable
{
yield ['<b>!</b>', '<b>!</b>'];
yield ['<b>!</b>', new StringableObject('<b>!</b>')];
}

#[DataProvider('dataAfterCheckbox')]
public function testAfterCheckbox(string $expected, string|Stringable $content): void
{
$this->assertSame(
'<label><input name="test[]" value="1" type="checkbox">' . $expected . ' One</label>' . "\n"
. '<label><input name="test[]" value="2" type="checkbox">' . $expected . ' Two</label>',
(new CheckboxList('test'))
->items([1 => 'One', 2 => 'Two'])
->afterCheckbox($content)
->withoutContainer()
->render(),
);
}

public function testAddIndividualInputAttributes(): void
{
$this->assertSame(
Expand Down Expand Up @@ -903,5 +945,7 @@ public function testImmutability(): void
$this->assertNotSame($widget, $widget->uncheckValue(null));
$this->assertNotSame($widget, $widget->separator(''));
$this->assertNotSame($widget, $widget->itemFormatter(null));
$this->assertNotSame($widget, $widget->beforeCheckbox(''));
$this->assertNotSame($widget, $widget->afterCheckbox(''));
}
}
44 changes: 44 additions & 0 deletions tests/Widget/RadioListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@

use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use Stringable;
use Yiisoft\Html\Html;
use Yiisoft\Html\Tests\Objects\StringableObject;
use Yiisoft\Html\Tests\Support\IntegerEnum;
use Yiisoft\Html\Tests\Support\StringEnum;
use Yiisoft\Html\Widget\RadioList\RadioItem;
Expand Down Expand Up @@ -832,6 +834,46 @@ public function testStringable(): void
);
}

public static function dataBeforeRadio(): iterable
{
yield ['<b>*</b>', '<b>*</b>'];
yield ['<b>*</b>', new StringableObject('<b>*</b>')];
}

#[DataProvider('dataBeforeRadio')]
public function testBeforeRadio(string $expected, string|Stringable $content): void
{
$this->assertSame(
'<label>' . $expected . '<input name="test" value="1" type="radio"> One</label>' . "\n"
. '<label>' . $expected . '<input name="test" value="2" type="radio"> Two</label>',
(new RadioList('test'))
->items([1 => 'One', 2 => 'Two'])
->beforeRadio($content)
->withoutContainer()
->render(),
);
}

public static function dataAfterRadio(): iterable
{
yield ['<b>!</b>', '<b>!</b>'];
yield ['<b>!</b>', new StringableObject('<b>!</b>')];
}

#[DataProvider('dataAfterRadio')]
public function testAfterRadio(string $expected, string|Stringable $content): void
{
$this->assertSame(
'<label><input name="test" value="1" type="radio">' . $expected . ' One</label>' . "\n"
. '<label><input name="test" value="2" type="radio">' . $expected . ' Two</label>',
(new RadioList('test'))
->items([1 => 'One', 2 => 'Two'])
->afterRadio($content)
->withoutContainer()
->render(),
);
}

public function testImmutability(): void
{
$widget = new RadioList('test');
Expand Down Expand Up @@ -859,5 +901,7 @@ public function testImmutability(): void
$this->assertNotSame($widget, $widget->uncheckValue(null));
$this->assertNotSame($widget, $widget->separator(''));
$this->assertNotSame($widget, $widget->itemFormatter(null));
$this->assertNotSame($widget, $widget->beforeRadio(''));
$this->assertNotSame($widget, $widget->afterRadio(''));
}
}
Loading