wisam-alhennawi / lara-forms-builder
This is my package lara-forms-builder
Installs: 2 167
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 2
Forks: 2
Open Issues: 4
Language:Blade
Requires
- php: ^8.1
- illuminate/support: ^10.0|^9.0
- livewire/livewire: ^3.0
- spatie/laravel-package-tools: ^1.13.0
Requires (Dev)
- laravel/pint: ^1.0
- nunomaduro/collision: ^6.0
- nunomaduro/larastan: ^2.0.1
- orchestra/testbench: ^8.0|^7.0
- pestphp/pest: ^1.21
- pestphp/pest-plugin-laravel: ^1.1
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^10.0|^9.5
- spatie/laravel-ray: ^1.26
- dev-main
- v2.x-dev
- v2.0.0
- v2.0.0-beta.1
- v1.x-dev
- v1.9.1
- v1.9.0
- v1.8.3
- v1.8.2
- v1.8.1
- v1.8.0
- v1.7.0
- v1.6.0
- v1.5.0
- v1.4.0
- v1.3.0
- v1.2.2
- v1.2.1
- v1.2.0
- v1.1.0
- v1.0.0
- v0.4.0
- v0.3.0
- v0.2.2
- v0.2.1
- 0.2.0
- 0.1.0
- dev-dependabot/github_actions/dependabot/fetch-metadata-2.2.0
- dev-feature/wrapper-error-field
- dev-feature/typing-time-attributes
- dev-dependabot/github_actions/aglipanci/laravel-pint-action-2.4
- dev-bugfix/extra-validate-in-multi-step-form
- dev-feature/fix-alpine-scripts-definition
- dev-feature/fix-file-upload
- dev-feature/checkbox-readonly
- dev-feature/improve-setup-command
This package is auto-updated.
Last update: 2024-11-14 16:33:20 UTC
README
About
The main functionality of this package is:
- Generate Livewire forms (Show, Create, Update) by using one command and one Livewire component.
Requirements
The following dependencies are required to use the package:
💡 => You can install it with Auto Setup & Configuration.
Note that (pikaday & moment) npm packages is required only if you have a date field within your form.
Installation
composer require wisam-alhennawi/lara-forms-builder
Upgrade Guide
If you want to use the package in an existing project that use v1 the following changed are required.
all placed uses $this->property
should be replaced with $this->formProperties['property']
// V1 $this->email // V2 $this->formProperties['email'] // V1 $this->rules['email'] // V2 $this->rules['formProperties.email']
Auto Setup & Configuration
php artisan make:lara-forms-builder-setup
This command will do the following:
- Install
"laravel/jetstream": "^4.0"
with"livewire/livewire": "^3.0"
if not installed. Installing jetstream will install"tailwindcss": "^3.0"
&"alpinejs": "^3.0"
. - Install
"pikaday": "^1.0"
and"moment": "^2.0"
npm packages and make required configuration. - Add confirmation modal component to
app.blade.php
layout. - publish
lara-forms-builder.php
config file and make required configuration. - publish
lara-forms-builder.css
assets file and make required configuration. - Run
npm install
&npm run build
.
Configuration
Publishing Assets
-
Config (Mandatory)
You Must publish the config file and add it to the
tailwind.config.js
in order to apply the styles:php artisan vendor:publish --tag="lara-forms-builder-config"
This is the contents of the published config file:
return [ 'default_group_wrapper_class' => 'lfb-group-wrapper', 'default_field_wrapper_class' => 'lfb-field-wrapper', 'card_field_error_wrapper_classes' => 'shadow mb-4 overflow-hidden rounded-md col-span-2 sm:col-span-2', 'primary_button_classes' => 'lfb-primary-button', 'secondary_button_classes' => 'lfb-secondary-button', 'footer_buttons_wrapper_classes' => 'lfb-buttons-wrapper', 'previous_button_classes' => 'lfb-secondary-button', 'next_button_classes' => 'lfb-primary-button', ];
Update
tailwind.config.js
:export default { content: [ './config/lara-forms-builder.php', ], theme: { extend: { colors: { 'primary': '', // #7c8e63 'secondary': '', // #aebf85 'danger': '' // #DC3545 }, }, }, };
-
CSS (Mandatory)
Publishing css file is Mandatory to apply styles.
php artisan vendor:publish --tag="lara-forms-builder-assets"
That will make a new css file
lara-forms-builder.css
in thepublic/vendor/lara-forms-builder/css/
directory. After that you must import this file with yourresources/css/app.css
by adding:@import "../../public/vendor/lara-forms-builder/css/lara-forms-builder.css";
And feel free to edit the default style in
lara-forms-builder.css
to fulfil your form requirements style. -
Translation (optional)
php artisan vendor:publish --tag="lara-forms-builder-translations"
-
Views (optional)
php artisan vendor:publish --tag="lara-forms-builder-views"
Using date in form (optional)
Like it mention in the Requirements section if your form has a date field you must install required dependencies by following these steps:
-
Installing pikaday:
npm install pikaday
add these to your
resources/js/app.js
import Pikaday from 'pikaday'; window.Pikaday = Pikaday;
add these to your
resources/css/app.css
@import 'pikaday/css/pikaday.css';
-
Installing moment:
npm install moment
Use confirmation modal
In order to use the confirmation modal within your project you must include it globally in the default layout of your blade view where you want to use it.
So you can add @livewire('modals.confirmation')
to your views/layouts/app.blade.php
inside the html <body>
tag.
Usage
Create new Livewire from
By using this command you can create a new Livewire form depending on a model, additionally you can add [--langModelFileName=] tag to specify a lang file for model fields labels:
php artisan make:lara-forms-builder name model --langModelFileName=
Examples:
php artisan make:lara-forms-builder UserForm User --langModelFileName=users php artisan make:lara-forms-builder Users.UserForm User --langModelFileName=users //this will make a UserForm component inside Users directory.
Form Component Types and Attributes
Forms are specified in a declarative manner as an array of the fields
function in the form component class.
beforeFormProperties()
, afterFormProperties()
functions used to set options, values, etc. before/after setting the form properties (e.g. developers options in the following example).
saveDevelopers()
function used to make operation after create/update a model (e.g. developers ids & project id will be saved in pivot table in the following example).
Note: saveDevelopers()
functions should follow the naming convention of the form field name developers
.
public array $developersOptions = []; // For 'checkbox-group' options public array $userIdOptions = []; // For 'user_id' options public function beforeFormProperties(): void { $this->developersOptions = User::all(['id as value', 'name as label'])->toArray(); } public function afterFormProperties(): void { $this->formProperties['developers'] = $this->model->developers->pluck('id'); } protected function fields(): array { return [ [ 'fields' => [ 'title' => [ 'type' => 'input', 'label' => __('models/projects.fields.title'), 'readOnly' => true ], 'status' => [ 'type' => 'select', 'label' => __('models/projects.fields.status'), 'styled' => true, 'searchable' => true, 'options' => [ [ 'value' => '1', 'label' => __('Pending') ], [ 'value' => '2', 'label' => __('Active') ], [ 'value' => '3', 'label' => __('Completed') ] ] ], 'type' => [ 'type' => 'radio', 'label' => __('models/projects.fields.type'), 'options' => [ '1' => __('Public'), '2' => __('Private') ] ], 'starting_date' => [ 'type' => 'date-picker', 'label' => __('models/projects.fields.starting_date'), ], 'user_id' => [ 'type' => 'search-picker', 'label' => __('models/projects.fields.user_id'), 'searchPickerResultsProperty' => 'userIdOptions', 'placeholder' => __('Search for Team Leader'), ], 'is_accepted' => [ 'type' => 'checkbox', 'label' => __('models/projects.fields.is_accepted'), ], 'description' => [ 'type' => 'textarea', 'label' => __('models/projects.fields.description'), 'field_wrapper_class' => 'col-span-2', ], 'developers' => [ 'type' => 'checkbox-group', 'label' => __('models/projects.fields.developers'), 'options' => $this->developersOptions, ], 'document' => [ 'type' => 'file', 'label' => __('models/projects.fields.document'), ], ] ] ]; } public function saveDevelopers($validated_date) { $this->model->developers()->sync($validated_date); } public function getUserIdOptions($searchPickerTerm) { return User::select('id', 'name') ->where('name', 'like', '%' . $searchPickerTerm . '%') ->get() ->each(function($row){ $row->key = $row->id; $row->value = $row->name; $row->labels = collect(['White', 'Green', 'Blue', 'Red', 'Yellow'])->random(rand(0, 3))->toArray(); }) ->toArray(); } // will return ($user_id_search_picker_selected_value) which used in blade to display the selected option public function getUserIdSearchPickerSelectedValueProperty() { if ($this->formProperties['user_id']) { return User::find($this->formProperties['user_id'])->name; } return null; }
The definition above is then rendered as displayed in this screenshot (with additional language dependent translations for the labels required):
All form components have the following general properties:
type
(mandatory): Specifies the kind of form component, see the following subsections for supported types and their individual propertieslabel
(mandatory): Label text of the component, can also include HTML tags (please handle responsibly and do not allow user input to be used as labels)validationAttribute
(optional): If set, the value will be used as the attribute label for validation messages. If not set, thelabel
is also used as a field name for validation messages.helpText
(optional): Help text displayed at the bottom of the componentreadOnly
(optional): When set to true, the form field does not allow input or changes and only displays the current valuerules
(optional): Validation rules to be applied for this field. If not set, Eloquent model rules for the field with the same name will be used if available, otherwise no rules are applied.field_wrapper_class
(optional): CSS class(es) to be added to the div that encloses the form componenttooltip
(optional): if set, the value is displayed as text in a tooltip on hover over a question mark icon rendered next to the label text
Type input
The input
form field is a classic html input element. It has the following additional properties:
inputType
(optional): Specifies the specific type of input, e.g. email, number, url. Default if not provided is text.secretValueToggle
(optional): Flag relevant for input type password, if set to true, an icon is displayed at the right end of the input field that allows to toggle the visilibity of the masked value on click.
Type textarea
The textarea
form field represents a text area and has the following additional properties:
rows
(optional): Defines the number of rows of the text area, default if not set is 5.
Type select
The select
form field is a select box for single selection. It has the following additional properties:
options
(mandatory): Specifies the options to be displayed in the select box, provided as an array of objects with attributesvalue
andlabel
or a nested array of group label to array of objects with attributesvalue
andlabel
when grouped.isGrouped
(optional): Defines whether the options are grouped, default when not set is false.styled
(optional, not combinable withisGrouped
): When set to true, uses a stylable div based select component instead of the html select element.searchable
(optional, only whenstyled
istrue
): When set to true, adds a search field that allows to filter the options for search expressions (simple case insensitive substring matching)
Type radio
The radio
form field represents radio buttons and has the following additional properties:
options
(mandatory): Specifies the options for the radio button selection as a simple arrayvalue => label
.
Type cards
The cards
form field is a special layout element used to select among different options by clicking on one of several cards with rich content and an icon. It has the following additional properties:
options
(mandatory): Specifies the options to be selected as an array of objects with attributesvalue
andlabel
(can be HTML).icon
(optional): SVG markup or URL to be displayed as icon in all cards, if not set, no icon is displayed.card_field_error_wrapper_class
(optional): CSS class(es) to be added to error message boxes.errorMessageIcon
(optional): Customized icon markup to be displayed in an error message, if not set, a default icon is used.
Type checkbox
The checkbox
form field is a single checkbox and does not have any additional properties.
Type checkbox-group
The checkbox-group
form field is a multi-select group of checkboxes. It has the following additional properties:
options
(mandatory): Specifies the values and labels for the checkboxes, provided as an array of objects with attributesvalue
andlabel
or a nested array of category label to array of objects with attributesvalue
andlabel
when grouped by category.hasCategory
(optional): Defines whether the checkbox entries are grouped by category, default if not set is false.
Type date-picker
The date-picker
form field adds a Pikaday date picker. It does not have any additional properties.
Type file
The file
form field represents a file input for a single file upload. It has the following additional properties:
preview
(optional): If set to the valueimage
, a preview of the uploaded or existing file is displayed. In order to properly show a preview of an existing file (when editing an existing model), the URL to download the existing file must be set as an additional property$this.{$key . '_preview'}
, e.g.contact_photo_preview
for a field keycontact_property
. The preview URL can be determined and set in theafterFormProperties
function.removeIcon
(optional): Customized icon markup to be displayed as the icon to remove/reset a selected file before saving. If not set, a default icon is used.
Since binary files are usually not directly stored as properties of an Eloquent model, but must be processed separately, this type of form field will in most cases need additional file handling logic in the implementing form. The implementation follows the principles of Livewire file uploads (https://laravel-livewire.com/docs/2.x/file-uploads) and essentially provides the view part of file upload. It is suggested to add the file handling in one of the callback or override functions, e.g. the save...
function of the property such as the following code snippet for a property attachment
:
public function saveAttachment($attachmentValue) { $attachmentValue->storeAs('attachments', $attachmentValue->getClientOriginalName()); }
Type search-picker
The search-picker
form field is an input field with search functionality which display the results as a list under the field. It has the following additional properties:
placeholder
(optional): Specifies the placeholder of the input field.searchPickerResultsProperty
(mandatory): Refers to the defined array which has the search results. Every element in the array should have the following structure:[ 'key' => '', 'value' => '', 'labels' => [] // optional ]
Note: getUserIdOptions()
, getUserIdSearchPickerSelectedValueProperty()
functions should follow the naming convention of the form field name user_id
.
Type trix-editor
The trix-editor
form field is a rich text editor which uses Trix under the hood. It has the general properties mentioned above excluding readOnly
.
In order to use the trix-editor form field you have to add the following to your blade:
<head>
<link rel="stylesheet" type="text/css" href="https://unpkg.com/trix@2.0.8/dist/trix.css">
<script type="text/javascript" src="https://unpkg.com/trix@2.0.8/dist/trix.umd.min.js"></script>
</head>
Please see the full documentation on the official Trix page .
Form Layout
Tabs
- A custom layout for components that utilize tabs to organize content.
- Each tab is represented as an array (in
fields()
method) containing'key'
,'title'
, and'content'
. Thekey
represents an internal technical key uniquely identifying the tab. Thetitle
property is used as label for both the tab navigation and the heading of the form; if an alternative (usually shortened) title for the navigation should be used, this can be specified with the optional propertynavTitle
. The'content'
array includes information about the form fields, their types, labels, options, and styling.
Multi-Step
- The Multi-Step feature is designed to facilitate the creation of multi-step forms with a Tabs Layout. It provides methods to initialize steps, set the active step number, navigate between steps, and retrieve information about the form's multi-step structure.
- Usage
- It works for now only with
Tabs Layout
and it is deactivated by default. - To enable the
multi-step
functionality, set theisMultiStep
property to true when configuring the form.
- It works for now only with
- Example:
use WisamAlhennawi\LaraFormsBuilder\LaraFormComponent; use WisamAlhennawi\LaraFormsBuilder\Traits\HasTabs; class CustomerForm extends LaraFormComponent { use HasTabs; public function mount(Customer $customer) { $this->mountForm($customer, [ 'activeTab' => 'address-data', 'hasTabs' => true, 'isMultiStep' => true, // Optional if you want to use the multi-step form feature ]); } protected function fields(): array { return [ [ 'key' => 'address-data', 'title' => __('Address Data'), 'content' => [ 'group_info' => [ 'group_wrapper_class' => 'grid grid-cols-4 gap-6', 'default_group_wrapper_class' => false ], 'fields' => [ // Fields for the 'Address Data' tab // Example: 'company' => [ 'type' => 'input', 'label' => __('models/customers.fields.company'), 'field_wrapper_class' => 'col-span-4', ], // ... other fields ], ], ], [ 'key' => 'contact-data', 'title' => __('Contact Data'), 'content' => [ 'group_info' => [ 'group_wrapper_class' => 'grid grid-cols-6 gap-6', 'default_group_wrapper_class' => false ], 'fields' => [ // Fields for the 'Contact Data' tab // Example: 'phone' => [ 'type' => 'input', 'label' => __('customers.fields.phone'), 'field_wrapper_class' => 'col-span-2', ], // ... other fields ], ], ], // .. other tabs ]; } // ... other component properties and methods }
Form Methods
-
protected function successMessage()
- Purpose:
- The
successMessage()
function is responsible for generating a success message based on the outcome of a form submission.
- The
- Custom Success Message:
- If a custom success message is provided through the
$customSuccessMessage
property, it will be used.
- If a custom success message is provided through the
- Default Success Messages:
- If no custom success message is set, default success messages are used for create and update modes.
trans('A new entry has been created successfully.') trans('Changes were saved successfully.')
- These default messages can be further customized by adding translation keys in the language file.
'A new '.$modelName.' has been created successfully.' 'The '.$modelName.' has been updated successfully.'
Example:'A new user has been created successfully.' 'The user has been updated successfully.'
- If no custom success message is set, default success messages are used for create and update modes.
- Displaying the Success Message:
- The success message is displayed to the user either as a flash message or through a browser event. The display method depends on the value of the
$hasSession
property, which is true by default.
- The success message is displayed to the user either as a flash message or through a browser event. The display method depends on the value of the
- Another way to customize the success message is to override the
successMessage()
method in the component class.
- Purpose:
-
protected function canSubmit(): bool
- Purpose: Check if the user is authorized to submit the form
-
protected function fieldIndicator($fieldKey): ?string
- Purpose:
- Display an indicator (*) for a required field in the form based on
required
rule in the rules array
- Display an indicator (*) for a required field in the form based on
- Customization:
- An indicator can be displayed based on a custom check (eg. conditional required rules like required_if), to do that
shouldDisplayIndicatorBasedOnCustomCheck($key)
should be overwritten: Example:
protected function shouldDisplayIndicatorBasedOnCustomCheck($key): bool { if ($key == 'email' && $this->formProperties['type'] == 'email') { return true; } return false; }
- An indicator can be displayed based on a custom check (eg. conditional required rules like required_if), to do that
- Purpose:
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.