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
40 changes: 1 addition & 39 deletions src/Views/Columns/LivewireComponentColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,5 @@ class LivewireComponentColumn extends Column
use LivewireComponentColumnConfiguration,
LivewireComponentColumnHelpers;

protected string $livewireComponent;

public function component(string $livewireComponent): self
{
$this->livewireComponent = (Str::startsWith($livewireComponent, 'livewire:')) ? substr($livewireComponent, 9) : $livewireComponent;

return $this;
}

public function getContents(Model $row): null|string|HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
{
if ($this->isLabel()) {
throw new DataTableConfigurationException('You can not use a label column with a component column');
}

$attributes = [];
$value = $this->getValue($row);

if ($this->hasAttributesCallback()) {
$attributes = call_user_func($this->getAttributesCallback(), $value, $row, $this);

if (! is_array($attributes)) {
throw new DataTableConfigurationException('The return type of callback must be an array');
}
}

$implodedAttributes = collect($attributes)->map(function ($value, $key) {
return ':'.$key.'="$'.$key.'"';
})->implode(' ');

return new HtmlString(Blade::render(
'<livewire:dynamic-component :component="$component" '.$implodedAttributes.' :wire:key="'.$row->{$row->getKeyName()}.'" />',
[
'component' => $this->livewireComponent,
...$attributes,
],
));

}
protected ?string $livewireComponent;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Configuration;

use Illuminate\Support\Str;

trait LivewireComponentColumnConfiguration
{
use ComponentColumnConfiguration;

protected string $componentView;
public function component(string $livewireComponent): self
{
$this->livewireComponent = (Str::startsWith($livewireComponent, 'livewire:')) ? substr($livewireComponent, 9) : $livewireComponent;

protected mixed $slotCallback;
return $this;
}
}
57 changes: 56 additions & 1 deletion src/Views/Traits/Helpers/LivewireComponentColumnHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,62 @@

namespace Rappasoft\LaravelLivewireTables\Views\Traits\Helpers;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;

trait LivewireComponentColumnHelpers
{
use ComponentColumnHelpers;
/**
* Retrieves the defined Component View
*/
public function getLivewireComponent(): ?string
{
return $this->livewireComponent ?? null;
}

/**
* Determines whether a Component View has been set
*/
public function hasLivewireComponent(): bool
{
return isset($this->livewireComponent);
}

public function getContents(Model $row): null|string|HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
{
if (! $this->hasLivewireComponent()) {
throw new DataTableConfigurationException('You must define a Livewire Component for this column');
}

if ($this->isLabel()) {
throw new DataTableConfigurationException('You can not use a label column with a Livewire Component column');
}

$attributes = [];
$value = $this->getValue($row);

if ($this->hasAttributesCallback()) {
$attributes = call_user_func($this->getAttributesCallback(), $value, $row, $this);

if (! is_array($attributes)) {
throw new DataTableConfigurationException('The return type of callback must be an array');
}
}

$implodedAttributes = collect($attributes)->map(function ($value, $key) {
return ':'.$key.'="$'.$key.'"';
})->implode(' ');

return new HtmlString(Blade::render(
'<livewire:dynamic-component :component="$component" '.$implodedAttributes.' :wire:key="'.$row->{$row->getKeyName()}.'" />',
[
'component' => $this->getLivewireComponent(),
...$attributes,
],
));

}
}
95 changes: 95 additions & 0 deletions tests/Unit/Views/Columns/LivewireComponentColumnTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Tests\Unit\Views\Columns;

use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
use Rappasoft\LaravelLivewireTables\Tests\Models\Pet;
use Rappasoft\LaravelLivewireTables\Tests\TestCase;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\Views\Columns\LivewireComponentColumn;

final class LivewireComponentColumnTest extends TestCase
{
public function test_can_set_the_column_title(): void
{
$column = LivewireComponentColumn::make('Name', 'name');

$this->assertSame('Name', $column->getTitle());
}

public function test_can_not_be_a_label_without_component(): void
{
$this->expectException(DataTableConfigurationException::class);

$column = LivewireComponentColumn::make('Total Users')->label(fn () => 'My Label')->getContents(Pet::find(1));

}

public function test_can_not_be_a_label_with_component(): void
{
$this->expectException(DataTableConfigurationException::class);

$column = LivewireComponentColumn::make('Total Users')->component('test-component')->label(fn () => 'My Label')->getContents(Pet::find(1));

}

public function test_can_add_livewire_component(): void
{
$column = LivewireComponentColumn::make('Name', 'name');

$this->assertFalse($column->hasLivewireComponent());
$column->component('test-component');
$this->assertTrue($column->hasLivewireComponent());
}

public function test_can_get_livewire_component(): void
{
$column = LivewireComponentColumn::make('Name', 'name');

$this->assertFalse($column->hasLivewireComponent());
$this->assertNull($column->getLivewireComponent());

$column->component('test-component');

$this->assertTrue($column->hasLivewireComponent());
$this->assertSame('test-component', $column->getLivewireComponent());
}

public function test_can_not_avoid_defining_livewire_component(): void
{
$this->expectException(DataTableConfigurationException::class);

$contents = LivewireComponentColumn::make('Name')->getContents(Pet::find(1));

}

public function test_attributes_should_return_array(): void
{
$this->expectException(DataTableConfigurationException::class);

$column = LivewireComponentColumn::make('Name')->component('test-component')->attributes(fn ($value, $row, Column $column) => 'test');

$column->getContents(Pet::find(1));
}

public function test_can_check_attribute_callback_presence(): void
{
$column = LivewireComponentColumn::make('Name', 'name')->component('test-component');
$this->assertFalse($column->hasAttributesCallback());
}

public function test_can_set_attribute_callback(): void
{
$column = LivewireComponentColumn::make('Name', 'name')->component('test-component');
$this->assertFalse($column->hasAttributesCallback());

$column->attributes(function ($row) {
return [
'class' => '!rounded-lg self-center',
'default' => true,
];
});

$this->assertTrue($column->hasAttributesCallback());
}
}