diff --git a/src/ListView.php b/src/ListView.php index d510759de..0e4881fc9 100644 --- a/src/ListView.php +++ b/src/ListView.php @@ -6,7 +6,7 @@ use Closure; use InvalidArgumentException; -use Yiisoft\Html\Tag\Div; +use Yiisoft\Html\Html; use Yiisoft\View\Exception\ViewNotFoundException; use Yiisoft\View\View; @@ -20,11 +20,21 @@ final class ListView extends BaseListView private ?Closure $afterItem = null; private ?Closure $beforeItem = null; + /** + * @psalm-var non-empty-string|null + */ + private ?string $itemsWrapperTag = 'ul'; + private array $itemsWrapperAttributes = []; + /** * @var callable|string|null */ private $itemView = null; + /** + * @psalm-var non-empty-string|null + */ + private ?string $itemViewTag = 'li'; private array $itemViewAttributes = []; private string $separator = "\n"; private array $viewParams = []; @@ -81,6 +91,36 @@ public function beforeItem(Closure $value): self return $new; } + /** + * Set the HTML tag for the items wrapper. + * + * @param string|null $tag + * @return $this + */ + public function itemsWrapperTag(?string $tag): self + { + if ($tag === '') { + throw new InvalidArgumentException('The "itemsWrapperTag" property cannot be empty.'); + } + + $new = clone $this; + $new->itemsWrapperTag = $tag; + return $new; + } + + /** + * Set the HTML attributes for the container of the items wrapper. + * + * @param array $values + * @return $this + */ + public function itemsWrapperAttributes(array $values): self + { + $new = clone $this; + $new->itemsWrapperAttributes = $values; + return $new; + } + /** * Return new instance with itemView closure. * @@ -108,6 +148,23 @@ public function itemView(string|Closure $value): self return $new; } + /** + * Set the HTML tag for the container of item view. + * + * @param string|null $tag + * @return $this + */ + public function itemViewTag(?string $tag): self + { + if ($tag === '') { + throw new InvalidArgumentException('The "itemViewTag" property cannot be empty.'); + } + + $new = clone $this; + $new->itemViewTag = $tag; + return $new; + } + /** * return new instance with the HTML attributes for the container of item view. * @@ -182,14 +239,16 @@ protected function renderItem(array|object $data, mixed $key, int $index): strin } if ($this->itemView instanceof Closure) { - $content = (string) call_user_func($this->itemView, $data, $key, $index, $this); + $content = (string)call_user_func($this->itemView, $data, $key, $index, $this); } - return Div::tag() - ->attributes($this->itemViewAttributes) - ->content("\n" . $content) - ->encode(false) - ->render(); + return $this->itemViewTag === null + ? $content + : Html::tag($this->itemViewTag) + ->attributes($this->itemViewAttributes) + ->content("\n" . $content) + ->encode(false) + ->render(); } /** @@ -217,7 +276,13 @@ protected function renderItems(array $items, \Yiisoft\Validator\Result $filterVa } } - return implode($this->separator, $rows); + $content = implode($this->separator, $rows); + + return $this->itemsWrapperTag === null + ? $content + : Html::tag($this->itemsWrapperTag, "\n" . $content . "\n", $this->itemsWrapperAttributes) + ->encode(false) + ->render(); } /** @@ -238,7 +303,7 @@ private function renderAfterItem(array|object $data, mixed $key, int $index): st $result = ''; if (!empty($this->afterItem)) { - $result = (string) call_user_func($this->afterItem, $data, $key, $index, $this); + $result = (string)call_user_func($this->afterItem, $data, $key, $index, $this); } return $result; @@ -262,7 +327,7 @@ private function renderBeforeItem(array|object $data, mixed $key, int $index): s $result = ''; if (!empty($this->beforeItem)) { - $result = (string) call_user_func($this->beforeItem, $data, $key, $index, $this); + $result = (string)call_user_func($this->beforeItem, $data, $key, $index, $this); } return $result; diff --git a/tests/ListView/BaseTest.php b/tests/ListView/BaseTest.php index c1c22e2c9..69f9bd695 100644 --- a/tests/ListView/BaseTest.php +++ b/tests/ListView/BaseTest.php @@ -27,16 +27,18 @@ public function testAfterItemBeforeItem(): void Assert::equalsWithoutLE( << +