Proof of Concept Livewire alternative
Good day to all. I recently spent a day tinkering with an idea. I use StimulusJS in my work a lot, and I wanted to try to make a Livewire clone based on stimulus just for fun. I've got a working prototype, and wanted to get some feedback on the API and semantics this thing uses, as well as to see if anyone is interested in this kind of thing.
Here's an example Component class:
class Test extends ReactiveComponentBase
{
public bool $actionCalled = false;
public int $count = 0;
public ?string $name;
public function __construct(
int $count = 0,
bool $actionCalled = false,
string $name = null
)
{
parent::__construct();
$this->count = $count;
$this->actionCalled = $actionCalled;
$this->name = $name;
}
public function render()
{
return view('test-reactive');
}
protected function synced(string $prop, string $value = null)
{
if ($prop === 'name') {
$this->validateOnly('name', ['min:5']);
}
}
public function test()
{
$this->actionCalled = true;
}
public function increment()
{
$this->count = $this->count + 1;
$this->validate([
'count' => ['numeric', 'min:5'],
]);
}
public function refresh()
{
$this->count = 0;
$this->actionCalled = false;
$this->name = '';
}
}
ReactiveComponentBase extends a regular Laravel component class, so you can use all features that that entails.
Here's that component's template:
<div {{ $attributes }}>
<h1>I am a test reactive component</h1>
@if($actionCalled)
<h2>Action is called</h2>
@endif
<h2>Count is: {{ $count }}</h2>
@error('count')
<div>{{ $message }}</div>
@enderror
<h2>Name is: {{ $name }}</h2>
<input type="text" name="name"
value="{{ $name }}"
data-action="input->reactive#react"
data-reactive-action-debounce="250"
data-reactive-action="sync"
data-reactive-sync-prop="name">
<div>
@error('name')
<span>{{ $message }}</span>
@enderror
</div>
<button data-action="reactive#react"
data-reactive-action="test">React!</button>
<button data-action="reactive#react"
data-reactive-action="refresh">Refresh!</button>
<button data-action="reactive#react"
data-reactive-action="increment">Increment!</button>
</div>
And here's how you include the component on your page: <x-reactive-component component="reactive.test" class="hello-world" />.
If anyone thinks this might be interesting I'd be glad to hear your thoughts!
Please or to participate in this conversation.