fuelviews / laravel-forms
Laravel forms package
Requires
- php: ^8.2
- spatie/laravel-package-tools: ^1.16
Requires (Dev)
- fuelviews/laravel-layouts-wrapper: ^0.0
- fuelviews/laravel-parameter-tagging: ^0.0
- laravel/pint: ^1.14
- livewire/livewire: ^3.5
- nunomaduro/collision: ^8.1.1||^7.10.0
- orchestra/testbench: ^9.0.0||^8.22.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-arch: ^2.7
- pestphp/pest-plugin-laravel: ^2.3
- spatie/laravel-googletagmanager: ^2.7
README
Laravel forms package
Installation
You can require the package via composer:
composer require fuelviews/laravel-forms
You can install the package with:
php artisan forms:install
You can publish the config file with:
php artisan vendor:publish --tag="forms-config"
This is the contents of the published config file:
return [ 'forms' => [ 'free_estimate' => [ 'production_url' => 'https://fuelforms.com/api/f/', 'development_url' => 'https://development.fuelforms.com/api/f/', 'gtm_event' => 'Form_Submit', 'gtm_event_gclid' => 'Form_Submit_Gclid', ], 'contact_us' => [ 'production_url' => 'https://fuelforms.com/api/f/', 'development_url' => 'https://development.fuelforms.com/api/f/', 'gtm_event' => 'Form_Submit', 'gtm_event_gclid' => 'Form_Submit_Gclid', ], 'careers' => [ 'production_url' => 'https://fuelforms.com/api/f/', 'development_url' => 'https://development.fuelforms.com/api/f/', 'gtm_event' => 'Form_Submit_Applicant', ], ], 'modal' => [ 'title' => 'Your Project Info', 'form_key' => 'free_estimate', 'steps' => [ 1 => [ 'heading' => 'Where do you need painting?', 'locations' => [ 'inside', 'outside', 'cabinets', ], ], ], 'tos' => [ 'enabled' => true, 'content' => 'By clicking "Submit" above, I expressly consent to...', ], 'optional_div' => [ 'enabled' => true, 'title' => 'Looking to work with us?', 'link_text' => 'Apply Here', 'link_route' => 'welcome', ], ], 'validation' => [ 'default' => [ 'firstName' => 'required|min:2|max:24', 'lastName' => 'required|min:2|max:24', 'email' => 'required|email', 'phone' => 'required|min:7|max:19', 'message' => 'nullable|max:255', ], 'free_estimate' => [ 'firstName' => 'required|min:2|max:24', 'lastName' => 'required|min:2|max:24', 'email' => 'required|email', 'phone' => 'required|min:7|max:19', 'message' => 'nullable|max:255', ], 'contact_us' => [ 'firstName' => 'required|min:2|max:24', 'lastName' => 'required|min:2|max:24', 'email' => 'required|email', 'phone' => 'required|min:7|max:19', 'message' => 'nullable|max:255', ], 'steps' => [ 1 => [ 'location' => 'required|in:inside,outside,cabinets', ], 2 => [ 'firstName' => 'required|min:2|max:24', 'lastName' => 'required|min:2|max:24', 'email' => 'required|email', 'phone' => 'required|min:7|max:19', 'zipCode' => 'required|min:4|max:9', 'message' => 'nullable|max:255', 'location' => 'required|in:inside,outside,cabinets', ], ], ], 'spam_redirects' => [ 'yelp' => 'https://yelp.com', 'bbb' => 'https://bbb.org', ], ];
Optionally, you can publish the views using
php artisan vendor:publish --tag="forms-views"
Register Middleware
Register middleware in your app/Http/Kernel.php file.
// GTM tracking... protected $middleware = [ \Illuminate\Session\Middleware\StartSession::class, \Spatie\GoogleTagManager\GoogleTagManagerMiddleware::class, ]; // Query params tracking... protected $middlewareGroups = [ 'web' => [ \Fuelviews\ParameterTagging\Http\Middleware\HandleGclid::class, \Fuelviews\ParameterTagging\Http\Middleware\HandleUtm::class, ], ];
Configure spatie google tag manager package
Publish spatie google tag manager config file:
php artisan vendor:publish --provider="Spatie\GoogleTagManager\GoogleTagManagerServiceProvider" --tag="config"
Edit app/googletagmanager.php
return [ /* * The Google Tag Manager id, should be a code that looks something like "gtm-xxxx". */ 'id' => env('GOOGLE_TAG_MANAGER_ID', 'GTM-XXXXXX'), /* * Enable or disable script rendering. Useful for local development. */ 'enabled' => env('GOOGLE_TAG_MANAGER_ENABLED', true), /* * If you want to use some macro's you 'll probably store them * in a dedicated file. You can optionally define the path * to that file here and we will load it for you. */ 'macroPath' => env('GOOGLE_TAG_MANAGER_MACRO_PATH', ''), /* * The key under which data is saved to the session with flash. */ 'sessionKey' => env('GOOGLE_TAG_MANAGER_SESSION_KEY', '_googleTagManager'), /* * Configures the Google Tag Manager script domain. * Modify this value only if you're using "Google Tag Manage: Web Container" client * to serve gtm.js for your web container. Else, keep the default value. */ 'domain' => env('GOOGLE_TAG_MANAGER_DOMAIN', 'www.googletagmanager.com'), ];
Form Usage (basic)
Include form method type, form method route, spam strap in the start and end of the form, form key, fake submit button, and a real submit button.
<form method="POST" action="{{ route('forms.validate') }}"> <input type="text" name="isSpam" style="display:none" /> /* Form fields here */ <x-forms::meta /> <input type="hidden" name="form_key" value="contact_us" /> <input type="text" name="gotcha" class="hidden" /> <x-forms::buttons.fake-button :buttonText="'Submit'" /> <x-forms::buttons.submit-button :buttonText="'Submit'" /> </form>
Form usage example
<form method="POST" action="{{ route('forms.validate') }}" class="mt-16">
<div class="grid grid-cols-1 gap-x-6 gap-y-2 sm:grid-cols-2">
<input type="text" name="_gotcha" style="display:none" />
<div>
<label for="firstName" class="block text-sm font-semibold leading-6 text-gray-900">
First name
</label>
<div class="mt-1">
<input
type="text"
name="firstName"
id="firstName"
wire:model="firstName"
autocomplete="given-name"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern="[A-Za-z]{2,}"
title="First name must be at least 2 letters and only contain letters." />
@error('firstName')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div>
<label for="lastName" class="block text-sm font-semibold leading-6 text-gray-900">
Last name
</label>
<div class="mt-1">
<input
type="text"
name="first-name"
id="lastName"
wire:model="lastName"
autocomplete="family-name"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern=".{2,}"
title="Last name must be at least 2 characters." />
@error('lastName')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<label for="email" class="block text-sm font-semibold leading-6 text-gray-900">
Email
</label>
<div class="mt-1">
<input
id="email"
name="email"
type="email"
wire:model="email"
autocomplete="email"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
@error('email')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<div class="flex justify-between text-sm leading-6">
<label for="phone" class="block font-semibold text-gray-900">Phone</label>
</div>
<div class="mt-1">
<input
type="tel"
name="phone"
id="phone"
wire:model="phone"
autocomplete="tel"
aria-describedby="phone-description"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
pattern="[\s\d\-\(\)]*?(\d[\s\d\-\(\)]*?){7,11}"
title="Phone number must have 7 to 11 digits and may include parentheses, spaces, and hyphens."
/>
@error('phone')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
<div class="sm:col-span-2">
<div class="flex justify-between text-sm leading-6">
<label for="message" class="block text-sm font-semibold leading-6 text-gray-900">
How can we help you?
</label>
<p id="message-description" class="text-gray-400">Max 255 characters</p>
</div>
<div class="mt-1">
<textarea
id="message"
name="message"
wire:model="message"
rows="4"
aria-describedby="message-description"
class="block w-full rounded-md border-0 px-3.5 py-2 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"></textarea>
@error('message')
<span class="flex pl-1 pt-2 text-sm text-red-600">{{ $message }}</span>
@enderror
</div>
</div>
</div>
<x-forms::meta />
<input type="hidden" name="form_key" value="contact_us" />
<input type="text" name="gotcha" class="hidden" />
<div class="mt-10 flex justify-end border-t border-gray-900/10 pt-8">
<x-forms::buttons.fake-button :buttonText="'Submit'" />
<x-forms::buttons.submit-button :buttonText="'Submit'" />
</div>
</form>
Form Modal Usage (basic)
Include forms-modal into your layouts.app.blade.php, trigger with a button. You can customize which layout blade file is used in the config/forms.php file
<button onclick="Livewire.dispatch('openModal')">Show Modal</button> @livewire('forms-modal')
Tailwindcss classes
Add laravel-forms to your tailwind.config.js file.
content: [ './vendor/fuelviews/laravel-*/resources/**/*.{js,vue,blade.php}', ]
Testing
composer test
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
Support us
Fuelviews is a web development agency based in Portland, Maine. You'll find an overview of all our projects on our website.
License
The MIT License (MIT). Please see License File for more information.