Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #211: ListView::itemViewAttributes() accepts Closure as parameter. #212

34 changes: 29 additions & 5 deletions src/ListView.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ final class ListView extends BaseListView
* @psalm-var non-empty-string|null
*/
private ?string $itemViewTag = 'li';
private array $itemViewAttributes = [];
private array|Closure $itemViewAttributes = [];
samdark marked this conversation as resolved.
Show resolved Hide resolved
private string $separator = "\n";
private array $viewParams = [];
private ?View $view = null;
Expand Down Expand Up @@ -166,11 +166,25 @@ public function itemViewTag(?string $tag): self
}

/**
* return new instance with the HTML attributes for the container of item view.
* Return new instance with the HTML attributes for the container of item view.
* If this property is specified as a callback, it must return an array of attributes and have the following
glpzzz marked this conversation as resolved.
Show resolved Hide resolved
* signature:
*
* @param array $values Attribute values indexed by attribute names.
* ```php
* function ($data, $key, $index, $widget)
* ```
*
* Also, each attribute value can be a closure too, with the same signature as in:
glpzzz marked this conversation as resolved.
Show resolved Hide resolved
*
* ```php
* [
* 'class' => static fn($data, $key, $index, $widget) => "custom-class-{$data['id']}",
* ]
* ```
* @param array|Closure $values Attribute values indexed by attribute names.
samdark marked this conversation as resolved.
Show resolved Hide resolved
* @return ListView
*/
public function itemViewAttributes(array $values): self
public function itemViewAttributes(array|Closure $values): self
{
$new = clone $this;
$new->itemViewAttributes = $values;
Expand Down Expand Up @@ -242,10 +256,20 @@ protected function renderItem(array|object $data, mixed $key, int $index): strin
$content = (string)call_user_func($this->itemView, $data, $key, $index, $this);
}

$itemViewAttributes = is_callable($this->itemViewAttributes)
? (array)call_user_func($this->itemViewAttributes, $data, $key, $index, $this)
: $this->itemViewAttributes;

foreach ($itemViewAttributes as $i => $attribute) {
if (is_callable($attribute)) {
$itemViewAttributes[$i] = $attribute($data, $key, $index, $this);
samdark marked this conversation as resolved.
Show resolved Hide resolved
}
}

return $this->itemViewTag === null
? $content
: Html::tag($this->itemViewTag)
->attributes($this->itemViewAttributes)
->attributes($itemViewAttributes)
->content("\n" . $content)
->encode(false)
->render();
Expand Down
83 changes: 83 additions & 0 deletions tests/ListView/BaseTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -407,4 +407,87 @@ public function testNoItemViewTagNoItemsWrapperTag(): void
->render(),
);
}

public function testClosureForItemViewAttributes(): void
{
Assert::equalsWithoutLE(
<<<HTML
<div>
<ul>
<li data-item-id="1" data-item-key="0" data-item-index="0">
<div>Id: 1</div><div>Name: John</div><div>Age: 20</div>
</li>
<li data-item-id="2" data-item-key="1" data-item-index="1">
<div>Id: 2</div><div>Name: Mary</div><div>Age: 21</div>
</li>
</ul>
<div>Page <b>1</b> of <b>1</b></div>
</div>
HTML,
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes(static fn (array $data, $key, $index, $widget) => [
'data-item-id' => $data['id'],
'data-item-key' => $key,
'data-item-index' => $index,
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
->render(),
);
}

public function testItemViewAttributesWithClosure(): void
{
Assert::equalsWithoutLE(
<<<HTML
<div>
<ul>
<li class="id-1-key-0-index-0">
<div>Id: 1</div><div>Name: John</div><div>Age: 20</div>
</li>
<li class="id-2-key-1-index-1">
<div>Id: 2</div><div>Name: Mary</div><div>Age: 21</div>
</li>
</ul>
<div>Page <b>1</b> of <b>1</b></div>
</div>
HTML,
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes([
'class' => static fn(array $data, $key, $index) => "id-{$data['id']}-key-{$key}-index-{$index}",
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
->render(),
);
}

public function testClosureForItemViewAttributesWithClosure(): void
{
Assert::equalsWithoutLE(
<<<HTML
<div>
<ul>
<li class="id-1-key-0-index-0">
<div>Id: 1</div><div>Name: John</div><div>Age: 20</div>
</li>
<li class="id-2-key-1-index-1">
<div>Id: 2</div><div>Name: Mary</div><div>Age: 21</div>
</li>
</ul>
<div>Page <b>1</b> of <b>1</b></div>
</div>
HTML,
ListView::widget()
->itemView(dirname(__DIR__) . '/Support/view/_listview.php')
->itemViewAttributes(static fn (array $data, $key, $index) => [
'class' => static fn(array $data, $key, $index) => "id-{$data['id']}-key-{$key}-index-{$index}",
])
->dataReader($this->createOffsetPaginator($this->data, 10))
->separator(PHP_EOL)
->render(),
);
}
}
Loading