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
41 changes: 11 additions & 30 deletions src/Views/Columns/LivewireComponentColumn.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,40 +16,21 @@ class LivewireComponentColumn extends Column
use LivewireComponentColumnConfiguration,
LivewireComponentColumnHelpers;

/**
* The Livewire Component assigned to this Column
*/
protected ?string $livewireComponent;

/**
* Gets the contents for current row
*/
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,
],
));
$this->runPreChecks();

$attributes = $this->retrieveAttributes($row);

return $this->getHtmlString($attributes, $this->getTable().'-'.$row->{$row->getKeyName()});

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

trait LivewireComponentColumnConfiguration
{
/**
* Defines which component to use
*/
public function component(string $livewireComponent): self
{
$this->livewireComponent = (Str::startsWith($livewireComponent, 'livewire:')) ? substr($livewireComponent, 9) : $livewireComponent;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

namespace Rappasoft\LaravelLivewireTables\Views\Columns\Traits\Helpers;

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

trait LivewireComponentColumnHelpers
{
/**
Expand All @@ -13,10 +18,84 @@ public function getLivewireComponent(): ?string
}

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

/**
* Retrieves attributes based on callback
*/
protected function retrieveAttributes(Model $row): array
{
$value = $this->getValue($row);

$attributes = ['value' => $value];

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');
}
}

return $attributes;
}

/**
* Runs pre-checks
*/
protected function runPreChecks(): bool
{
if (! $this->hasLivewireComponent()) {
throw new DataTableConfigurationException('You must define a Livewire Component for this column');

return false;
}

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

return false;
}

return true;
}

/**
* Implodes defined attributes to be used
*/
protected function implodeAttributes(array $attributes): string
{
return collect($attributes)->map(function ($value, $key) {
return ':'.$key.'="$'.$key.'"';
})->implode(' ');
}

/**
* getBlade Render
*/
protected function getBlade(array $attributes, string $key)
{
return Blade::render(
'<livewire:dynamic-component :component="$component" :key="$key" '.$this->implodeAttributes($attributes).' />',
[
'component' => $this->getLivewireComponent(),
'key' => $key,
...$attributes,
],
);
}

/**
* Gets HTML STring
*/
protected function getHtmlString(array $attributes, string $key): HtmlString
{
return new HtmlString($this->getBlade($attributes, $key));

}
}
40 changes: 40 additions & 0 deletions tests/Http/Livewire/PetsTableWithLivewireColumn.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire;

use Illuminate\Support\Facades\App;
use Rappasoft\LaravelLivewireTables\Tests\Models\Pet;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\Views\Columns\LivewireComponentColumn;

class PetsTableWithLivewireColumn extends BaseTable
{
public $model = Pet::class;

public function changeLocale(string $locale)
{
App::setLocale($locale);
}

public function configure(): void
{
$this->setPrimaryKey('id');
}

public function columns(): array
{
return [
Column::make('ID', 'id')
->sortable(),
Column::make('Name', 'name')
->sortable(),
LivewireComponentColumn::make('LW', 'name')
->component('test-livewire-column-component')->attributes(function ($columnValue, $row) {
return [
'type' => 'test',
'name' => $row->name,
];
}),
];
}
}
27 changes: 27 additions & 0 deletions tests/Http/Livewire/TestComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Tests\Http;

use Closure;
use Illuminate\Contracts\View\View;
use Illuminate\View\Component;

class TestComponent extends Component
{
public int $testItem = 0;

public function __construct(int $age)
{
$this->testItem = $age * 110;
}

/**
* Get the view / contents that represent the component.
*/
public function render(): View|Closure|string
{
return \Illuminate\Support\Facades\Blade::render(
'<div>'.($this->testItem ?? 'Unknown').'</div>');

}
}
28 changes: 28 additions & 0 deletions tests/Http/Livewire/TestLivewireColumnComponent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire;

class TestLivewireColumnComponent extends \Livewire\Component
{
public string $id;

public string $name;

public string $value;

public string $type;

/**
* Get the view / contents that represent the component.
*/
public function render()
{
return \Illuminate\Support\Facades\Blade::render(
'<div>'.
'<div>Name:'.($this->name ?? 'Unknown').'</div>'.
'<div>Type:'.($this->type ?? 'Unknown').'</div>'.
'</div>'
);

}
}
3 changes: 3 additions & 0 deletions tests/TestServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class TestServiceProvider extends ServiceProvider
public function boot(): void
{
Blade::component('test-component', TestComponent::class);

\Livewire\Livewire::component('test-livewire-column-component', \Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\TestLivewireColumnComponent::class);

$this->loadViewsFrom(__DIR__.'/views', 'livewire-tables-test');

}
Expand Down
80 changes: 80 additions & 0 deletions tests/Unit/Views/Columns/LivewireComponentColumnTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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

use Illuminate\Database\Eloquent\Model;
use PHPUnit\Framework\Attributes\Group;
use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
use Rappasoft\LaravelLivewireTables\Tests\Models\Pet;
Expand Down Expand Up @@ -89,4 +90,83 @@ public function test_can_set_attribute_callback(): void

$this->assertTrue(self::$columnInstance->hasAttributesCallback());
}

public static function setup_with_public_methods()
{
\Livewire\Livewire::component('test-livewire-column-component', \Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\TestLivewireColumnComponent::class);

$row = Pet::find(1);

$temp = (new class('name', 'name') extends LivewireComponentColumn
{
public function pubRetrieveAttributes(Model $row)
{
return $this->retrieveAttributes($row);
}

public function pubImplodeAttributes(array $attributes)
{
return $this->implodeAttributes($attributes);
}

public function pubGetBlade(array $attributes, string $key)
{
return $this->getBlade($attributes, $key);
}

public function pubGetHtmlString(array $attributes, string $key)
{
return $this->getHtmlString($attributes, $key);
}
})->component('test-livewire-column-component')->attributes(function ($columnValue, $row) {
return [
'type' => 'test',
'name' => $row->name,
];
});

$temp->setTable('test-table');

return $temp;
}

public function test_can_get_attributes_correctly(): void
{
$row = Pet::find(1);
$temp = self::setup_with_public_methods();
$key = 'test-table-'.$row->{$row->getKeyName()};

$this->assertSame(['type' => 'test', 'name' => 'Cartman'], $temp->pubRetrieveAttributes($row));

$this->assertSame(':type="$type" :name="$name"', $temp->pubImplodeAttributes($temp->pubRetrieveAttributes($row)));
}

public function test_can_get_blade_correctly(): void
{
$row = Pet::find(1);
$temp = self::setup_with_public_methods();
$key = 'test-table-'.$row->{$row->getKeyName()};

$this->assertStringContainsString('wire:snapshot="{&quot;data&quot;:{&quot;id&quot;:null,&quot;name&quot;:&quot;Cartman&quot;,&quot;value&quot;:null,&quot;type&quot;:&quot;test&quot;}', $temp->pubGetBlade($temp->pubRetrieveAttributes($row), $key));

$this->assertStringContainsString('<div>Name:Cartman</div><div>Type:test</div>', $temp->pubGetBlade($temp->pubRetrieveAttributes($row), $key));
}

public function test_can_get_html_string_correctly(): void
{
$row = Pet::find(1);
$temp = self::setup_with_public_methods();
$key = 'test-table-'.$row->{$row->getKeyName()};

$this->assertStringContainsString('<div>Name:Cartman</div><div>Type:test</div>', $temp->pubGetHtmlString($temp->pubRetrieveAttributes($row), $key));
}

public function test_can_get_contents_correctly(): void
{
$row = Pet::find(1);
$temp = self::setup_with_public_methods();
$key = 'test-table-'.$row->{$row->getKeyName()};

$this->assertStringContainsString('<div>Name:Cartman</div><div>Type:test</div>', $temp->getContents($row));
}
}
Loading
Loading