Skip to content
This repository was archived by the owner on Jan 2, 2024. It is now read-only.

Commit f7c12a4

Browse files
authored
Livewire and hidden fix (#3)
* wip * WIP Livewire * Added Livewire test * Livewire documentation * Update composer.json
1 parent 936da0b commit f7c12a4

25 files changed

+307
-28
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
All notable changes to `laravel-form-components` will be documented in this file
44

5+
## 1.2.0 - 2020-08-01
6+
7+
- Validation support for Laravel Livewire
8+
- Make hidden inputs visually hidden
9+
510
## 1.1.0 - 2020-07-18
611

712
- added support for Bootstrap 4

README.md

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ A set of Blade components to rapidly build forms with [Tailwind CSS Custom Forms
1414
* Support for [Tailwind CSS Custom Forms](https://tailwindcss-custom-forms.netlify.app) and [Bootstrap 4 Forms](https://getbootstrap.com/docs/4.0/components/forms/).
1515
* Component logic independent from Blade views, the Tailwind and Bootstrap views use the same logic.
1616
* Bind a target to a form (or a set of elements) to provide default values.
17+
* Support for [Laravel Livewire](https://laravel-livewire.com)
1718
* Support for Spatie's [laravel-translatable](https://github.com/spatie/laravel-translatable).
1819
* Re-populate forms with [old input](https://laravel.com/docs/master/requests#old-input).
1920
* Validation errors.
@@ -159,6 +160,51 @@ You can override the `@bind` directive by passing a target directly to the eleme
159160
</x-form>
160161
```
161162

163+
#### Laravel Livewire
164+
165+
You can use the `@wire` and `@endwire` directives to use bind a form to a Livewire component. Let's take a look at the `ContactForm` example from the official Livewire documentation.
166+
167+
```php
168+
use Livewire\Component;
169+
170+
class ContactForm extends Component
171+
{
172+
public $name;
173+
public $email;
174+
175+
public function submit()
176+
{
177+
$this->validate([
178+
'name' => 'required|min:6',
179+
'email' => 'required|email',
180+
]);
181+
182+
Contact::create([
183+
'name' => $this->name,
184+
'email' => $this->email,
185+
]);
186+
}
187+
188+
public function render()
189+
{
190+
return view('livewire.contact-form');
191+
}
192+
}
193+
```
194+
195+
Normally you would use a `wire:model` attribute to bind a component property with a form element. By using the `@wire` directive, this package will automatically use the `wire:model` attribute instead of the `name` attribute.
196+
197+
```blade
198+
<x-form wire:submit.prevent="submit">
199+
@wire
200+
<x-form-input name="name" />
201+
<x-form-input name="email" />
202+
@endwire
203+
204+
<x-form-submit>Save Contact</x-form-submit>
205+
</form>
206+
```
207+
162208
### Select elements
163209

164210
Besides the `name` attribute, the `select` element has a required `options` attribute, which should be a simple *key-value* array.

composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@
2727
],
2828
"require": {
2929
"php": "^7.4",
30-
"illuminate/support": "^7.4"
30+
"illuminate/support": "^7.22.4"
3131
},
3232
"require-dev": {
33+
"livewire/livewire": "^1.3.2",
3334
"orchestra/testbench-browser-kit": "^5.1",
3435
"phpunit/phpunit": "^8.5",
3536
"spatie/laravel-translatable": "^4.4"

resources/views/bootstrap-4/form-checkbox.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
11
<div class="form-check">
22
<input {!! $attributes->merge(['class' => 'form-check-input ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
33
type="checkbox"
4-
name="{{ $name }}"
54
value="{{ $value }}"
65

6+
@if($isWired())
7+
wire:model="{{ $name }}"
8+
@else
9+
name="{{ $name }}"
10+
@endif
11+
12+
713
@if($checked)
814
checked="checked"
915
@endif

resources/views/bootstrap-4/form-input.blade.php

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<div class="form-group">
1+
<div class="@if($type === 'hidden') d-none @else form-group @endif">
22
<x-form-label :label="$label" :for="$name" />
33

44
<div class="input-group">
@@ -11,9 +11,14 @@
1111
@endisset
1212

1313
<input {!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
14-
name="{{ $name }}"
1514
type="{{ $type }}"
16-
value="{{ $value }}"
15+
16+
@if($isWired())
17+
wire:model="{{ $name }}"
18+
@else
19+
name="{{ $name }}"
20+
value="{{ $value }}"
21+
@endif
1722
/>
1823

1924
@isset($append)

resources/views/bootstrap-4/form-radio.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<div class="form-check">
22
<input {!! $attributes->merge(['class' => 'form-check-input ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
33
type="radio"
4-
name="{{ $name }}"
4+
5+
@if($isWired())
6+
wire:model="{{ $name }}"
7+
@else
8+
name="{{ $name }}"
9+
@endif
10+
511
value="{{ $value }}"
612

713
@if($checked)

resources/views/bootstrap-4/form-select.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
<div class="form-group">
22
<x-form-label :label="$label" :for="$name" />
33

4-
<select name="{{ $name }}"
4+
<select
5+
@if($isWired())
6+
wire:model="{{ $name }}"
7+
@else
8+
name="{{ $name }}"
9+
@endif
10+
511
@if($multiple)
612
multiple
713
@endif

resources/views/bootstrap-4/form-textarea.blade.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
<div class="form-group">
22
<x-form-label :label="$label" :for="$name" />
33

4-
<textarea {!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
5-
name="{{ $name }}">{!! $value !!}</textarea>
4+
<textarea
5+
@if($isWired())
6+
wire:model="{{ $name }}"
7+
@else
8+
name="{{ $name }}"
9+
@endif
10+
11+
{!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
12+
>@unless($isWired()){!! $value !!}@endunless</textarea>
613

714
{!! $help ?? null !!}
815

resources/views/tailwind/form-checkbox.blade.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
<div class="flex">
1+
<div class="flex flex-col">
22
<label class="flex items-center">
33
<input {!! $attributes->merge(['class' => 'form-checkbox']) !!}
44
type="checkbox"
5-
name="{{ $name }}"
65
value="{{ $value }}"
76

7+
@if($isWired())
8+
wire:model="{{ $name }}"
9+
@else
10+
name="{{ $name }}"
11+
@endif
12+
813
@if($checked)
914
checked="checked"
1015
@endif

resources/views/tailwind/form-input.blade.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
1-
<div class="mt-4">
1+
<div class="@if($type === 'hidden') hidden @else mt-4 @endif">
22
<label class="block">
33
<x-form-label :label="$label" />
44

55
<input {!! $attributes->merge([
66
'class' => 'form-input block w-full ' . ($label ? 'mt-1' : '')
77
]) !!}
8-
name="{{ $name }}"
9-
type="{{ $type }}"
10-
value="{{ $value }}"
11-
/>
8+
@if($isWired())
9+
wire:model="{{ $name }}"
10+
@else
11+
name="{{ $name }}"
12+
value="{{ $value }}"
13+
@endif
14+
15+
type="{{ $type }}" />
1216
</label>
1317

1418
@if($hasErrorAndShow($name))

resources/views/tailwind/form-radio.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
<label class="inline-flex items-center">
33
<input {!! $attributes->merge(['class' => 'form-radio']) !!}
44
type="radio"
5-
name="{{ $name }}"
5+
6+
@if($isWired())
7+
wire:model="{{ $name }}"
8+
@else
9+
name="{{ $name }}"
10+
@endif
11+
612
value="{{ $value }}"
713

814
@if($checked)

resources/views/tailwind/form-select.blade.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,13 @@
22
<label class="block">
33
<x-form-label :label="$label" />
44

5-
<select name="{{ $name }}"
5+
<select
6+
@if($isWired())
7+
wire:model="{{ $name }}"
8+
@else
9+
name="{{ $name }}"
10+
@endif
11+
612
@if($multiple)
713
multiple
814
@endif

resources/views/tailwind/form-textarea.blade.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,15 @@
22
<label class="block">
33
<x-form-label :label="$label" />
44

5-
<textarea {!! $attributes->merge([
6-
'class' => 'form-textarea block w-full ' . ($label ? 'mt-1' : '')
7-
]) !!}
8-
name="{{ $name }}">{!! $value !!}</textarea>
5+
<textarea
6+
@if($isWired())
7+
wire:model="{{ $name }}"
8+
@else
9+
name="{{ $name }}"
10+
@endif
11+
12+
{!! $attributes->merge(['class' => 'form-textarea block w-full ' . ($label ? 'mt-1' : '')]) !!}
13+
>@unless($isWired()){!! $value !!}@endunless</textarea>
914
</label>
1015

1116
@if($hasErrorAndShow($name))

src/Components/Component.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
use Illuminate\Support\Str;
66
use Illuminate\View\Component as BaseComponent;
7+
use ProtoneMedia\LaravelFormComponents\FormDataBinder;
78

89
abstract class Component extends BaseComponent
910
{
@@ -20,4 +21,24 @@ public function render()
2021

2122
return str_replace('{framework}', $framework, $config['view']);
2223
}
24+
25+
/**
26+
* Returns a boolean wether the form is wired to a Livewire component.
27+
*
28+
* @return boolean
29+
*/
30+
public function isWired(): bool
31+
{
32+
return app(FormDataBinder::class)->isWired();
33+
}
34+
35+
/**
36+
* The inversion of 'isWired()'.
37+
*
38+
* @return boolean
39+
*/
40+
public function isNotWired(): bool
41+
{
42+
return !$this->isWired();
43+
}
2344
}

src/Components/Form.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProtoneMedia\LaravelFormComponents\Components;
44

5+
use Illuminate\Support\Facades\View;
56
use Illuminate\Support\ViewErrorBag;
67

78
class Form extends Component
@@ -29,7 +30,7 @@ public function __construct(string $method = 'POST')
2930
*/
3031
public function hasError($bag = 'default'): bool
3132
{
32-
$errors = request()->session()->get('errors') ?: new ViewErrorBag;
33+
$errors = View::shared('errors', fn () => request()->session()->get('errors', new ViewErrorBag));
3334

3435
return $errors->getBag($bag)->isNotEmpty();
3536
}

src/Components/FormCheckbox.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function __construct(
3434
$this->checked = true;
3535
}
3636

37-
if (!session()->hasOldInput()) {
37+
if (!session()->hasOldInput() && $this->isNotWired()) {
3838
$boundValue = $this->getBoundValue($bind, $name);
3939

4040
$this->checked = is_null($boundValue) ? $default : $boundValue;

src/Components/FormSelect.php

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,22 @@ public function __construct(
3131
$this->label = $label;
3232
$this->options = $options;
3333

34-
$default = $this->getBoundValue($bind, $name) ?: $default;
34+
if ($this->isNotWired()) {
35+
$default = $this->getBoundValue($bind, $name) ?: $default;
3536

36-
$this->selectedKey = old($name, $default);
37+
$this->selectedKey = old($name, $default);
38+
}
3739

3840
$this->multiple = $multiple;
3941
$this->showErrors = $showErrors;
4042
}
4143

4244
public function isSelected($key): bool
4345
{
46+
if ($this->isWired()) {
47+
return false;
48+
}
49+
4450
if ($this->selectedKey === $key) {
4551
return true;
4652
}

src/Components/HandlesDefaultAndOldValue.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ private function setValue(
1212
$default = null,
1313
$language = null
1414
) {
15+
if ($this->isWired()) {
16+
return;
17+
}
18+
1519
if (!$language) {
1620
$default = $this->getBoundValue($bind, $name) ?: $default;
1721

src/Components/HandlesValidationErrors.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProtoneMedia\LaravelFormComponents\Components;
44

5+
use Illuminate\Support\Facades\View;
56
use Illuminate\Support\ViewErrorBag;
67

78
trait HandlesValidationErrors
@@ -32,7 +33,7 @@ public function hasErrorAndShow(string $name, string $bag = 'default'): bool
3233
*/
3334
public function hasError(string $name, string $bag = 'default'): bool
3435
{
35-
$errors = request()->session()->get('errors') ?: new ViewErrorBag;
36+
$errors = View::shared('errors', fn () => request()->session()->get('errors', new ViewErrorBag));
3637

3738
$name = str_replace(['[', ']'], ['.', ''], $name);
3839

0 commit comments

Comments
 (0)