Please check out my latest package here: https://github.com/bastinald/laravel-livewire-forms
A dynamic, responsive Laravel Livewire form component with realtime validation, file uploads, array fields, and more.
Make sure you've installed Laravel Livewire.
Installing this package via composer:
composer require kdion4891/laravel-livewire-forms
This package was designed to work well with Laravel frontend scaffolding.
If you're just doing scaffolding now, you'll need to add @stack('scripts')
, @livewireScripts
, and @livewireStyles
blade directives to your resources/views/layouts/app.blade.php
file:
<!-- Styles -->
<link href="{{ asset('css/app.css') }}" rel="stylesheet">
@livewireStyles
...
<!-- Scripts -->
<script src="{{ asset('js/app.js') }}"></script>
@livewireScripts
@stack('scripts')
This package also uses Font Awesome for icons. If you don't already have it installed, it's as simple as:
npm install @fortawesome/fontawesome-free
Then add the following line to resources/sass/app.scss
:
@import '~@fortawesome/fontawesome-free/css/all.min.css';
Now all that's left is to compile the assets:
npm install && npm run dev
Using the make
command:
php artisan make:form UserCreateForm --model=User
This creates your new form component in the app/Http/Livewire
folder.
After making a component, you may want to edit the fields
, success
, saveAndStayResponse
and saveAndGoBackResponse
methods:
class UserCreateForm extends FormComponent
{
public function fields()
{
return [
Field::make('Name')->input()->rules('required'),
];
}
public function success()
{
User::create($this->form_data);
}
public function saveAndStayResponse()
{
return redirect()->route('users.create');
}
public function saveAndGoBackResponse()
{
return redirect()->route('users.index');
}
}
You don't have to use the render()
method in your form component or worry about a component view, because the package handles that automatically.
Protip: you can add the FillsColumns
trait to your model for automatic $fillable
s via database column names.
You use form components in views just like any other Livewire component:
@livewire('user-create-form')
Now all you have to do is update your form component class!
Optional Eloquent model instance attached to the form component. This is passed in via the @livewire
blade directive.
Example:
@livewire('user-edit-form', ['model' => $user])
Example of using the model in the component success
method:
public function success()
{
$this->model->update($this->form_data);
}
An array of the current data present in the form. This data is keyed with each field name.
Example:
$name = $this->form_data['name'];
A static property which sets the disk to use for file uploads. Defaults to public
.
Example:
private static $storage_disk = 's3';
Or, via .env
to apply globally:
FORM_STORAGE_DISK="s3"
A static property which sets the path to use for file uploads. Defaults to uploads
.
Example:
private static $storage_path = 'avatars';
Or, via .env
to apply globally:
FORM_STORAGE_PATH="avatars"
This method returns an array of Field
s to use in the form.
Example:
public function fields()
{
return [
Field::make('Name')->input()->rules('required'),
Field::make('Email')->input('email')->rules(['required', 'email', 'unique:users,email']),
Field::make('Password')->input('password')->rules(['required', 'min:8', 'confirmed']),
Field::make('Confirm Password', 'password_confirmation')->input('password'),
];
}
Declaring Field
s is similar to declaring Laravel Nova fields. Jump to the field declaration section to learn more.
This method is used to set rules to ignore during realtime validation.
Example:
public function rulesIgnoreRealtime()
{
return ['confirmed', new MyCustomRule];
}
This method defines what actions should take place when the form is successfully submitted and validation has passed.
Example:
public function success()
{
$this->form_data['password'] = Hash::make($this->form_data['password']);
User::create($this->form_data);
}
This method defines the response after successful submission via the Save
button.
Example:
public function saveAndStayResponse()
{
return redirect()->route('users.edit', $this->model->id);
}
This method defines the response after successful submission via the Save & Go Back
button.
Example:
public function saveAndGoBackResponse()
{
return redirect()->route('users.index');
}
This method sets the initial form properties. If you have to override it, be sure to call $this->setFormProperties()
.
The model instance passed to the form component.
Example:
public function mount($model = null)
{
$this->setFormProperties();
// my custom code
}
This method renders the form component view. If you have to override it, be sure to return $this->formView()
.
Example:
public function render()
{
// my custom code
return $this->formView();
}
The Field
class is used to declare your form fields.
public function fields()
{
$brand_options = Brand::orderBy('name')->get()->pluck('id', 'name')->all();
return [
Field::make('Brand', 'brand_id')->select($brand_options)->help('Please select a brand.'),
Field::make('Name')->input()->rules(['required', Rule::unique('cars', 'name')->ignore($this->model->id)]),
Field::make('Photos')->file()->multiple()->rules('required'),
Field::make('Color')->select(['Red', 'Green', 'Blue']),
Field::make('Owners')->array([
ArrayField::make('Name')->input()->placeholder('Name')->rules('required'),
ArrayField::make('Phone')->input('tel')->placeholder('Phone')->rules('required'),
])->rules('required'),
Field::make('Insurable')->checkbox()->placeholder('Is the car insurable?')->rules('accepted'),
Field::make('Fuel Type')->radio(['Gas', 'Diesel', 'Electric'])->default('Diesel'),
Field::make('Features')->checkboxes(['Stereo', 'Bluetooth', 'Navigation'])->rules('required|min:2'),
Field::make('Description')->textarea(),
];
}
The label to use for the form field, e.g. First Name
.
The name to use for the form field. If null, it will use a snake cased $label
.
Basic field example:
Field::make('First Name')->input()->rules('required|min:2'),
Relationship field example:
$brand_options = Brand::orderBy('name')->get()->pluck('id', 'name')->all();
return [
Field::make('Brand', 'brand_id')->select($brand_options)->rules(['required', Rule::exists('brands', 'id')]),
...
Sets the field to be an input
element. Defaults to text
.
Optional HTML5 input type to use for the input.
Example:
Field::make('Email Address')->input('email'),
Sets the field to be a file
input element.
File fields should have a nullable text
database column, and be cast to array
in your model.
This array will be populated with useful info for each file, including file
, disk
, name
, size
, and mime_type
.
Example migration:
$table->text('photos')->nullable();
Example model casting:
protected $casts = ['photos' => 'array'];
Example field declaration:
Field::make('Photos')->file(),
You can allow multiple file selections using the multiple()
method:
Field::make('Photos')->file()->multiple(),
Sets the field to be a textarea
element.
The amount of rows to use for the textarea. Defaults to 2
.
Example:
Field::make('Description')->textarea(5),
Sets the field to be a select
dropdown element.
An array of options to use for the select.
Example using a sequential array:
Field::make('Colors')->select(['Red', 'Green', 'Blue']),
Example using an associative array:
Field::make('Colors')->select(['Red' => '#ff0000', 'Green' => '#00ff00', 'Blue' => '#0000ff']),
When using associative arrays, the keys will be used for the option labels, and the values for the option values.
Sets the field to be a checkbox
element.
Checkbox fields should have a nullable boolean
database column.
Example migration:
$table->boolean('accepts_terms')->nullable();
Example field declaration:
Field::make('Accepts Terms')->checkbox()->placeholder('Do you accept our TOS?')->rules('accepted'),
If a placeholder()
is specified, it will be used as the checkbox label.
Sets the field to be multiple checkbox
elements.
An array of options to use for the checkboxes. Works the same as the select()
method.
Checkboxes fields should have a nullable text
database column, and be cast to array
in your model.
Example migration:
$table->text('features')->nullable();
Example model casting:
protected $casts = ['features' => 'array'];
Example field declaration:
Field::make('Features')->checkboxes(['Stereo', 'Bluetooth', 'Navigation'])->rules('required|min:2'),
Sets the field to be a radio
element.
An array of options to use for the radio. Works the same as the select()
method.
Example:
Field::make('Fuel Type')->radio(['Gas', 'Diesel', 'Electric'])->default('Diesel'),
Sets the field to be an array of fields.
An array of ArrayField
s to use. Jump to the array field declaration section to learn more.
Example:
Field::make('Owners')->array([
ArrayField::make('Full Name')->input()->placeholder('Full Name')->rules('required'),
ArrayField::make('Phone Number')->input('tel')->placeholder('Phone Number'),
]),
Use the sortable()
method to make the array fields sortable:
Field::make('Owners')->array([
ArrayField::make('Full Name')->input()->placeholder('Full Name')->rules('required'),
ArrayField::make('Phone Number')->input('tel')->placeholder('Phone Number'),
])->sortable(),
Sets the default value to use for the field.
The default value.
Example:
Field::make('City')->input()->default('Toronto'),
Sets the autocomplete value to use for the field.
The autocomplete value.
Example:
Field::make('Password')->input('password')->autocomplete('new-password'),
Sets the placeholder value to use for the field.
The placeholder value.
Example:
Field::make('Country')->input()->placeholder('What country do you live in?'),
Sets the help text to use below the field.
The help text.
Example:
Field::make('City')->input()->help('Please enter your current city.'),
Sets the Laravel validation rules to use for the field.
A string or array of Laravel validation rules.
Example using a string:
Field::make('Name')->input()->rules('required|min:2'),
Example using an array:
Field::make('City')->input()->rules(['required', Rule::in(['Toronto', 'New York']), new MyCustomRule]),
Sets a custom view to use for the field. Useful for more complex field elements not included in the package.
The custom view.
Example custom view file:
{{-- fields/custom-field.blade.php --}}
<div class="form-group row">
<label for="{{ $field->name }}" class="col-md-2 col-form-label text-md-right">
{{ $field->label }}
</label>
<div class="col-md">
<input
id="{{ $field->name }}"
type="text"
class="custom-field-class form-control @error($field->key) is-invalid @enderror"
wire:model.lazy="{{ $field->key }}">
@include('laravel-livewire-forms::fields.error-help')
</div>
</div>
Custom views are passed $field
, $form_data
, and $model
variables, as well as any other public component properties.
Example custom view field declaration:
Field::make('Custom Field')->view('fields.custom-field');
ArrayField
s are slightly different than Field
s. They should only be declared within the field array()
method.
They have most of the same methods available, except for the file()
and array()
methods.
They also have a columnWidth()
method unavailable to Field
s.
The name to use for the array field, e.g. phone_number
.
Array fields do not use labels. Rather, you should specify a placeholder()
for them instead.
Example:
ArrayField::make('phone_number')->input('tel')->placeholder('Phone Number')->rules('required'),
Optional Bootstrap 4 grid column width to use for the array field on desktop. If this is not set, the column will uniformly fit in the grid by default.
Example:
ArrayField::make('province')->select(['AB', 'BC', 'ON'])->placeholder('Province')->columnWidth(4),
You can also use auto
to have the column auto-fit the array field width:
ArrayField::make('old_enough')->checkbox()->placeholder('Old Enough')->columnWidth('auto'),
Publishing files is optional.
Publishing the form view files:
php artisan vendor:publish --tag=form-views
Publishing the config file:
php artisan vendor:publish --tag=form-config