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

Commit f037af0

Browse files
authored
Support for Bootstrap v4 (#1)
1 parent 2252b06 commit f037af0

22 files changed

+342
-32
lines changed

.travis.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,13 @@ cache:
77
matrix:
88
include:
99
- php: 7.4
10-
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-lowest'
10+
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-lowest' FORM_COMPONENTS_FRAMEWORK='tailwind'
1111
- php: 7.4
12-
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-stable'
12+
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-stable'FORM_COMPONENTS_FRAMEWORK='tailwind'
13+
- php: 7.4
14+
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-lowest'FORM_COMPONENTS_FRAMEWORK='bootstrap-4'
15+
- php: 7.4
16+
env: LARAVEL='7.*' TESTBENCH='5.*' COMPOSER_FLAGS='--prefer-stable'FORM_COMPONENTS_FRAMEWORK='bootstrap-4'
1317
fast_finish: true
1418

1519
before_install:

CHANGELOG.md

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

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

5+
## 1.1.0 - 2020-07-18
6+
7+
- added support for Bootstrap 4
8+
59
## 1.0.1 - 2020-07-18
610

711
- added `hasErrorAndShow` method to components

README.md

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ A set of Blade components to build forms with [Tailwind CSS Custom Forms](https:
1010

1111
## Features
1212

13-
* Components for input, textarea, select, multi-select, checkbox and radio elements
14-
* Support for [Tailwind CSS Custom Forms](https://tailwindcss-custom-forms.netlify.app)
15-
* Bind a target to a form (or a set of elements) to provide default values
16-
* Support for Spatie's [laravel-translatable](https://github.com/spatie/laravel-translatable)
17-
* Re-populate forms with [old input](https://laravel.com/docs/master/requests#old-input)
18-
* Validation errors
19-
* Components classes and Blade views fully customizable
20-
* Support for prefixing the components
21-
* Prepared for other CSS frameworks as well (in a future release)
13+
* Components for input, textarea, select, multi-select, checkbox and radio elements.
14+
* Support for [Tailwind CSS Custom Forms](https://tailwindcss-custom-forms.netlify.app) and [Bootstrap 4 Forms](https://getbootstrap.com/docs/4.0/components/forms/).
15+
* Bind a target to a form (or a set of elements) to provide default values.
16+
* Support for Spatie's [laravel-translatable](https://github.com/spatie/laravel-translatable).
17+
* Re-populate forms with [old input](https://laravel.com/docs/master/requests#old-input).
18+
* Validation errors.
19+
* Components classes and Blade views fully customizable.
20+
* Support for prefixing the components.
21+
* Component logic independent from Blade views, the Tailwind and Bootstrap views use the same logic.
2222

2323
## Requirements
2424

@@ -98,15 +98,15 @@ By default every element shows validation errors but you can hide them if you wa
9898
<x-form-textarea name="description" :show-errors="false" />
9999
```
100100

101-
### Default value
101+
### Default value and binds
102102

103103
You can use the `default` attribute to specify the default value of the element.
104104

105105
```blade
106106
<x-form-textarea name="motivation" default="I want to use this package because..." />
107107
```
108108

109-
### Binding a target
109+
#### Binding a target
110110

111111
Instead of setting a default value, you can also pass in a target, like an Eloquent model. Now the component will get the value from the target by the `name`.
112112

@@ -116,7 +116,7 @@ Instead of setting a default value, you can also pass in a target, like an Eloqu
116116

117117
In the example above, where `$video` is an Eloquent model, the default value will be `$video->description`.
118118

119-
### Binding a target to multiple elements
119+
#### Binding a target to multiple elements
120120

121121
You can also bind a target by using the `@bind` directive. This will bind the target to all elements until the `@endbind` directive.
122122

@@ -145,7 +145,7 @@ You can even mix targets!
145145
</x-form>
146146
```
147147

148-
### Override or remove a binding
148+
#### Override or remove a binding
149149

150150
You can override the `@bind` directive by passing a target directly to the element using the `:bind` attribute. If you want to remove a binding for a specific element, pass in `false`.
151151

@@ -240,7 +240,7 @@ php artisan vendor:publish --provider="ProtoneMedia\LaravelFormComponents\Suppor
240240

241241
You can find the Blade views in the `resources/views/vendor/form-components` folder. Optionally, in the `form-components.php` configuration file, you can change the location of the Blade view *per* component.
242242

243-
### Customize the components
243+
#### Component logic
244244

245245
You can bind your own component classes to any of the elements. In the `form-components.php` configuration file, you can change the class *per* component. As the logic for the components is quite complex, it is strongly recommended to duplicate the default component as a starting point and start editing. You'll find the default component classes in the `vendor/protonemedia/laravel-form-components/src/Components` folder.
246246

@@ -249,7 +249,6 @@ You can bind your own component classes to any of the elements. In the `form-com
249249
You can define a prefix in the `form-components.php` configuration file.
250250

251251
```php
252-
253252
return [
254253
'prefix' => 'tailwind',
255254
];
@@ -277,6 +276,60 @@ By the default, the errors messages are positioned under the element. To show th
277276
</x-form>
278277
```
279278

279+
### Submit button
280+
281+
The label defaults to *Submit* but you can use the slot to provide your own content.
282+
283+
```blade
284+
<x-form-submit>
285+
<span class="text-green-500">Send</span>
286+
</x-form-submit>
287+
```
288+
289+
### Bootstrap 4
290+
291+
You can switch to [Bootstrap 4](https://getbootstrap.com/docs/4.0/components/forms/) by updating the `framework` setting in the `form-components.php` configuration file.
292+
293+
```php
294+
return [
295+
'framework' => 'bootstrap-4',
296+
];
297+
```
298+
299+
There is a little bit of styling added to the `form.blade.php` view to add support for inline form groups. If you want to change it or remove it, [publish the assets](#customize-the-blade-views) and update the view file.
300+
301+
#### Input prepend and append
302+
303+
In addition to the Tailwind features, there is also support for [input groups](https://getbootstrap.com/docs/4.1/components/forms/#auto-sizing). Use the `prepend` and `append` slots to provide the contents.
304+
305+
```blade
306+
<x-form-input name="username" label="Username">
307+
@slot('prepend')
308+
<span>@</span>
309+
@endslot
310+
</x-form-input>
311+
312+
<x-form-input name="subdomain" label="Subdomain">
313+
@slot('append')
314+
<span>.protone.media</span>
315+
@endslot
316+
</x-form-input>
317+
```
318+
319+
#### Help text
320+
321+
You can add [block-level help text](https://getbootstrap.com/docs/4.1/components/forms/#help-text) to any element by using the `help` slot.
322+
323+
```blade
324+
<x-form-input name="username" label="Username">
325+
@slot('help')
326+
<small class="form-text text-muted">
327+
Your username must be 8-20 characters long.
328+
</small>
329+
@endslot
330+
</x-form-input>
331+
```
332+
280333
### Testing
281334

282335
``` bash
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<div class="form-check">
2+
<input {!! $attributes->merge(['class' => 'form-check-input ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
3+
type="checkbox"
4+
name="{{ $name }}"
5+
value="{{ $value }}"
6+
7+
@if($checked)
8+
checked="checked"
9+
@endif
10+
/>
11+
12+
<x-form-label :label="$label" :for="$name" class="form-check-label" />
13+
14+
{!! $help ?? null !!}
15+
16+
@if($hasErrorAndShow($name))
17+
<x-form-errors :name="$name" />
18+
@endif
19+
</div>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
@error($name)
2+
<div {!! $attributes->merge(['class' => 'invalid-feedback']) !!}>
3+
{{ $message }}
4+
</div>
5+
@enderror
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<div {!! $attributes->merge(['class' => 'form-group ' . ($hasError($name) ? 'is-invalid' : '')]) !!}>
2+
<x-form-label :label="$label" />
3+
4+
<div class="@if($inline) d-flex flex-row flex-wrap inline-space @endif">
5+
{!! $slot !!}
6+
</div>
7+
8+
{!! $help ?? null !!}
9+
10+
@if($hasErrorAndShow($name))
11+
<x-form-errors :name="$name" class="d-block" />
12+
@endif
13+
</div>
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<div class="form-group">
2+
<x-form-label :label="$label" :for="$name" />
3+
4+
<div class="input-group">
5+
@isset($prepend)
6+
<div class="input-group-prepend">
7+
<div class="input-group-text">
8+
{!! $prepend !!}
9+
</div>
10+
</div>
11+
@endisset
12+
13+
<input {!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
14+
name="{{ $name }}"
15+
type="{{ $type }}"
16+
value="{{ $value }}"
17+
/>
18+
19+
@isset($append)
20+
<div class="input-group-append">
21+
<div class="input-group-text">
22+
{!! $append !!}
23+
</div>
24+
</div>
25+
@endisset
26+
</div>
27+
28+
{!! $help ?? null !!}
29+
30+
@if($hasErrorAndShow($name))
31+
<x-form-errors :name="$name" />
32+
@endif
33+
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
@if($label)
2+
<label {!! $attributes !!}>{{ $label }}</label>
3+
@endif
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<div class="form-check">
2+
<input {!! $attributes->merge(['class' => 'form-check-input ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
3+
type="radio"
4+
name="{{ $name }}"
5+
value="{{ $value }}"
6+
7+
@if($checked)
8+
checked="checked"
9+
@endif
10+
/>
11+
12+
<x-form-label :label="$label" :for="$name" class="form-check-label" />
13+
14+
{!! $help ?? null !!}
15+
16+
@if($hasErrorAndShow($name))
17+
<x-form-errors :name="$name" />
18+
@endif
19+
</div>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<div class="form-group">
2+
<x-form-label :label="$label" :for="$name" />
3+
4+
<select name="{{ $name }}"
5+
@if($multiple)
6+
multiple
7+
@endif
8+
9+
{!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}>
10+
@foreach($options as $key => $option)
11+
<option value="{{ $key }}" @if($isSelected($key)) selected="selected" @endif>
12+
{{ $option }}
13+
</option>
14+
@endforeach
15+
</select>
16+
17+
{!! $help ?? null !!}
18+
19+
@if($hasErrorAndShow($name))
20+
<x-form-errors :name="$name" />
21+
@endif
22+
</div>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<button {!! $attributes->merge([
2+
'class' => 'btn btn-primary',
3+
'type' => 'submit'
4+
]) !!}>
5+
{!! trim($slot) ?: __('Submit') !!}
6+
</button>
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<div class="form-group">
2+
<x-form-label :label="$label" :for="$name" />
3+
4+
<textarea {!! $attributes->merge(['class' => 'form-control ' . ($hasError($name) ? 'is-invalid' : '')]) !!}
5+
name="{{ $name }}">{!! $value !!}</textarea>
6+
7+
{!! $help ?? null !!}
8+
9+
@if($hasErrorAndShow($name))
10+
<x-form-errors :name="$name" />
11+
@endif
12+
</div>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<form method="{{ $method }}" {!! $attributes->merge([
2+
'class' => $hasError() ? 'needs-validation' : ''
3+
]) !!}>
4+
<style>
5+
.inline-space > :not(template) {
6+
margin-right: 1.25rem;
7+
}
8+
</style>
9+
10+
@unless(in_array($method, ['HEAD', 'GET', 'OPTIONS']))
11+
@csrf
12+
@endunless
13+
14+
{!! $slot !!}
15+
</form>

src/Components/Form.php

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

33
namespace ProtoneMedia\LaravelFormComponents\Components;
44

5+
use Illuminate\Support\ViewErrorBag;
6+
57
class Form extends Component
68
{
79
/**
@@ -18,4 +20,17 @@ public function __construct(string $method = 'POST')
1820
{
1921
$this->method = strtoupper($method);
2022
}
23+
24+
/**
25+
* Returns a boolean wether the error bag is not empty.
26+
*
27+
* @param string $bag
28+
* @return boolean
29+
*/
30+
public function hasError($bag = 'default'): bool
31+
{
32+
$errors = request()->session()->get('errors') ?: new ViewErrorBag;
33+
34+
return $errors->getBag($bag)->isNotEmpty();
35+
}
2136
}

src/Components/HandlesValidationErrors.php

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,30 @@ trait HandlesValidationErrors
88
{
99
public $showErrors = true;
1010

11+
/**
12+
* Returns a boolean wether the given attribute has an error
13+
* and the should be shown.
14+
*
15+
* @param string $name
16+
* @param string $bag
17+
* @return boolean
18+
*/
1119
public function hasErrorAndShow(string $name, string $bag = 'default'): bool
1220
{
13-
if (!$this->showErrors) {
14-
return false;
15-
}
21+
return $this->showErrors
22+
? $this->hasError($name, $bag)
23+
: false;
24+
}
1625

26+
/**
27+
* Returns a boolean wether the given attribute has an error.
28+
*
29+
* @param string $name
30+
* @param string $bag
31+
* @return boolean
32+
*/
33+
public function hasError(string $name, string $bag = 'default'): bool
34+
{
1735
$errors = request()->session()->get('errors') ?: new ViewErrorBag;
1836

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

0 commit comments

Comments
 (0)