Skip to content

Commit 9a1e518

Browse files
committed
Initial Commit - Fix Livewire Component Column - Add Keys and Tests
1 parent c75c206 commit 9a1e518

File tree

5 files changed

+226
-32
lines changed

5 files changed

+226
-32
lines changed

src/Views/Columns/LivewireComponentColumn.php

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,40 +16,26 @@ class LivewireComponentColumn extends Column
1616
use LivewireComponentColumnConfiguration,
1717
LivewireComponentColumnHelpers;
1818

19+
/**
20+
* The Livewire Component assigned to this Column
21+
*
22+
* @var string|null
23+
*/
1924
protected ?string $livewireComponent;
2025

26+
/**
27+
* Gets the contents for current row
28+
*
29+
* @param Model $row
30+
* @return null|string|HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
31+
*/
2132
public function getContents(Model $row): null|string|HtmlString|DataTableConfigurationException|\Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
2233
{
23-
if (! $this->hasLivewireComponent()) {
24-
throw new DataTableConfigurationException('You must define a Livewire Component for this column');
25-
}
34+
$this->runPreChecks();
35+
36+
$attributes = $this->retrieveAttributes($row);
2637

27-
if ($this->isLabel()) {
28-
throw new DataTableConfigurationException('You can not use a label column with a Livewire Component column');
29-
}
30-
31-
$attributes = [];
32-
$value = $this->getValue($row);
33-
34-
if ($this->hasAttributesCallback()) {
35-
$attributes = call_user_func($this->getAttributesCallback(), $value, $row, $this);
36-
37-
if (! is_array($attributes)) {
38-
throw new DataTableConfigurationException('The return type of callback must be an array');
39-
}
40-
}
41-
42-
$implodedAttributes = collect($attributes)->map(function ($value, $key) {
43-
return ':'.$key.'="$'.$key.'"';
44-
})->implode(' ');
45-
46-
return new HtmlString(Blade::render(
47-
'<livewire:dynamic-component :component="$component" '.$implodedAttributes.' :wire:key="'.$row->{$row->getKeyName()}.'" />',
48-
[
49-
'component' => $this->getLivewireComponent(),
50-
...$attributes,
51-
],
52-
));
38+
return $this->getHtmlString($attributes, $this->getTable()."-".$row->{$row->getKeyName()});
5339

5440
}
5541
}

src/Views/Columns/Traits/Configuration/LivewireComponentColumnConfiguration.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@
66

77
trait LivewireComponentColumnConfiguration
88
{
9+
10+
/**
11+
* Defines which component to use
12+
*
13+
* @param string $livewireComponent
14+
* @return self
15+
*/
916
public function component(string $livewireComponent): self
1017
{
1118
$this->livewireComponent = (Str::startsWith($livewireComponent, 'livewire:')) ? substr($livewireComponent, 9) : $livewireComponent;

src/Views/Columns/Traits/Helpers/LivewireComponentColumnHelpers.php

Lines changed: 103 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,121 @@
22

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

5+
use Rappasoft\LaravelLivewireTables\Exceptions\DataTableConfigurationException;
6+
use Illuminate\Database\Eloquent\Model;
7+
use Illuminate\Support\Facades\Blade;
8+
use Illuminate\Support\HtmlString;
9+
510
trait LivewireComponentColumnHelpers
611
{
12+
713
/**
814
* Retrieves the defined Component View
9-
*/
15+
*
16+
* @return string|null
17+
*/
1018
public function getLivewireComponent(): ?string
1119
{
1220
return $this->livewireComponent ?? null;
1321
}
1422

23+
1524
/**
16-
* Determines whether a Component View has been set
17-
*/
25+
* Determines whether a Livewire Component has been set
26+
*
27+
* @return boolean
28+
*/
1829
public function hasLivewireComponent(): bool
1930
{
2031
return isset($this->livewireComponent);
2132
}
33+
34+
/**
35+
* Retrieves attributes based on callback
36+
*
37+
* @param Model $row
38+
* @return array
39+
*/
40+
protected function retrieveAttributes(Model $row): array
41+
{
42+
$value = $this->getValue($row);
43+
44+
$attributes = ['value' => $value];
45+
46+
if ($this->hasAttributesCallback()) {
47+
$attributes = call_user_func($this->getAttributesCallback(), $value, $row, $this);
48+
49+
if (! is_array($attributes)) {
50+
throw new DataTableConfigurationException('The return type of callback must be an array');
51+
}
52+
}
53+
return $attributes;
54+
}
55+
56+
/**
57+
* Runs pre-checks
58+
*
59+
* @return boolean
60+
*/
61+
protected function runPreChecks(): bool
62+
{
63+
if (! $this->hasLivewireComponent()) {
64+
throw new DataTableConfigurationException('You must define a Livewire Component for this column');
65+
return false;
66+
}
67+
68+
if ($this->isLabel()) {
69+
throw new DataTableConfigurationException('You can not use a label column with a Livewire Component column');
70+
return false;
71+
}
72+
73+
return true;
74+
}
75+
76+
/**
77+
* Implodes defined attributes to be used
78+
*
79+
* @param array $attributes
80+
* @return string
81+
*/
82+
protected function implodeAttributes(array $attributes): string
83+
{
84+
return collect($attributes)->map(function ($value, $key) {
85+
return ':'.$key.'="$'.$key.'"';
86+
})->implode(' ');
87+
}
88+
89+
/**
90+
* getBlade Render
91+
*
92+
* @param array $attributes
93+
* @param string $key
94+
*/
95+
protected function getBlade(array $attributes, string $key)
96+
{
97+
return Blade::render(
98+
'<livewire:dynamic-component :component="$component" :key="$key" '.$this->implodeAttributes($attributes).' />',
99+
[
100+
'component' => $this->getLivewireComponent(),
101+
'key' => $key,
102+
...$attributes,
103+
],
104+
);
105+
}
106+
107+
/**
108+
* Gets HTML STring
109+
*
110+
* @param array $attributes
111+
* @param string $key
112+
* @return HtmlString
113+
*/
114+
protected function getHtmlString(array $attributes, string $key): HtmlString
115+
{
116+
return new HtmlString($this->getBlade($attributes, $key));
117+
118+
}
119+
120+
121+
22122
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
3+
namespace Rappasoft\LaravelLivewireTables\Tests\Http\Livewire;
4+
5+
class TestComponent extends \Livewire\Component
6+
{
7+
public string $id;
8+
public string $name;
9+
public string $value;
10+
public string $type;
11+
12+
/**
13+
* Get the view / contents that represent the component.
14+
*/
15+
public function render()
16+
{
17+
return \Illuminate\Support\Facades\Blade::render(
18+
'<div>'.
19+
'<div>Name:'.($this->name ?? 'Unknown').'</div>'.
20+
'<div>Type:'.($this->type ?? 'Unknown').'</div>'.
21+
'</div>'
22+
);
23+
24+
}
25+
}

tests/Unit/Views/Columns/LivewireComponentColumnTest.php

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Rappasoft\LaravelLivewireTables\Tests\Models\Pet;
88
use Rappasoft\LaravelLivewireTables\Views\Column;
99
use Rappasoft\LaravelLivewireTables\Views\Columns\LivewireComponentColumn;
10+
use Illuminate\Database\Eloquent\Model;
1011

1112
#[Group('Columns')]
1213
final class LivewireComponentColumnTest extends ColumnTestCase
@@ -89,4 +90,79 @@ public function test_can_set_attribute_callback(): void
8990

9091
$this->assertTrue(self::$columnInstance->hasAttributesCallback());
9192
}
93+
94+
public static function setup_with_public_methods()
95+
{
96+
\Livewire\Livewire::component('test-component', \Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\TestComponent::class);
97+
98+
$row = Pet::find(1);
99+
100+
$temp = (new class("name", "name") extends LivewireComponentColumn
101+
{
102+
103+
public function pubRetrieveAttributes(Model $row)
104+
{
105+
return $this->retrieveAttributes($row);
106+
}
107+
108+
public function pubImplodeAttributes(array $attributes)
109+
{
110+
return $this->implodeAttributes($attributes);
111+
}
112+
113+
public function pubGetBlade(array $attributes, string $key)
114+
{
115+
return $this->getBlade($attributes,$key);
116+
}
117+
118+
public function pubGetHtmlString(array $attributes, string $key)
119+
{
120+
return $this->getHtmlString($attributes,$key);
121+
}
122+
123+
})->component('test-component')->attributes(function ($columnValue, $row) {
124+
return [
125+
'type' => "test",
126+
'name' => $row->name,
127+
];
128+
});
129+
130+
$temp->setTable('test-table');
131+
132+
return $temp;
133+
}
134+
135+
136+
public function test_can_get_attributes_correctly(): void
137+
{
138+
$row = Pet::find(1);
139+
$temp = self::setup_with_public_methods();
140+
$key = "test-table-".$row->{$row->getKeyName()};
141+
142+
$this->assertSame(['type' => 'test', 'name' => 'Cartman'], $temp->pubRetrieveAttributes($row));
143+
144+
$this->assertSame(':type="$type" :name="$name"', $temp->pubImplodeAttributes($temp->pubRetrieveAttributes($row)));
145+
}
146+
147+
public function test_can_get_blade_correctly(): void
148+
{
149+
$row = Pet::find(1);
150+
$temp = self::setup_with_public_methods();
151+
$key = "test-table-".$row->{$row->getKeyName()};
152+
153+
$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));
154+
155+
$this->assertStringContainsString('<div>Name:Cartman</div><div>Type:test</div>', $temp->pubGetBlade($temp->pubRetrieveAttributes($row),$key));
156+
}
157+
158+
public function test_can_get_html_string_correctly(): void
159+
{
160+
$row = Pet::find(1);
161+
$temp = self::setup_with_public_methods();
162+
$key = "test-table-".$row->{$row->getKeyName()};
163+
164+
$this->assertStringContainsString('<div>Name:Cartman</div><div>Type:test</div>', $temp->pubGetHtmlString($temp->pubRetrieveAttributes($row),$key));
165+
}
166+
92167
}
168+

0 commit comments

Comments
 (0)