Laravel 11 - How to Integrate Signature Pad
Laravel 11 - How to Integrate Signature Pad
This tutorial covers integrating a signature pad in Laravel 11, enabling electronic signatures for faster workflows, reduced paperwork, and streamlined approvals.
If you're a video person, feel free to skip the post and check out the video instead!
Step # 1 : Create fresh Laravel project or use existing project.
Two commands to create fresh laravel project
Global Command : laravel new signature
Or use
Non Global Command : composer create-project laravel/laravel --prefer-dist signature
Step # 2 : Access the project.
Open a terminal (e.g., Git Bash) and navigate to your Laravel project's root folder.
Git Bash : cd c:xampp/htdocs/signature
Step # 3 : Install Signpad package.
Run the following command to install the package.
Command : composer require creagia/laravel-sign-pad
Step # 4 : Publish the config, migration & assets.
Use the following command to publish the package configuration & migration.
Command : php artisan sign-pad:install
It will prompt you to run the migrations; type "yes," and you'll see the migration details followed by a prompt to star the repo on GitHub—type "no" to skip.
Use the following command to publish the .js assets.
Command : php artisan vendor:publish --tag=sign-pad-assets
Step # 5 : Update the User Model.
Update the User model with the following changes.
<?php
namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
// Include signature handling traits and contracts
use Creagia\LaravelSignPad\Concerns\RequiresSignature;
use Creagia\LaravelSignPad\Contracts\CanBeSigned;
// User model implements CanBeSigned for signature capabilities.
class User extends Authenticatable implements CanBeSigned
{
/** @use HasFactory<\Database\Factories\UserFactory> */
// Uses RequiresSignature for signature handling.
use HasFactory, Notifiable, RequiresSignature;
/**
* The attributes that are mass assignable.
*
* @var array<int, string>
*/
protected $fillable = [
'name',
'email',
'password',
];
/**
* The attributes that should be hidden for serialization.
*
* @var array<int, string>
*/
protected $hidden = [
'password',
'remember_token',
];
/**
* Get the attributes that should be cast.
*
* @return array<string, string>
*/
protected function casts(): array
{
return [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}
}
Step # 6 : Create and Update route.
Import the UserController class, which we will create in the next step, and include the following routes.
use App\Http\Controllers\UserController;
// Route to display the user creation form.
Route::get('/', [UserController::class, 'create']);
// Route to handle the form submission for creating a user and storing the signature.
Route::post('/confirm', [UserController::class, 'store']);
// Route to display the user's agreement details.
Route::get('/show/{user}', [UserController::class, 'show']);
Step # 7 : Create a controller.
Run the following command to generate the UserController.
Command : php artisan make:controller UserController
Replace the content of UserController.php with the provided code to handle user creation and signature storage.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Creagia\LaravelSignPad\Signature;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class UserController extends Controller
{
public function create()
{
//Return the form view.
return view('sign');
}
public function store(Request $request)
{
//Validate the data
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|min:8',
'sign' => 'required',
]);
//Create user with validated Data.
$user = User::create($validatedData);
// Process the signature data and save it as a PNG file.
$signatureData = str_replace('data:image/png;base64,', '', $validatedData['sign']);
$signatureData = base64_decode($signatureData);
$imageName = 'signatures/' . Str::uuid() . '.png';
Storage::disk('public')->put($imageName, $signatureData);
// Create and save the signature associated with the user.
$signature = new Signature();
$signature->model_type = User::class;
$signature->model_id = $user->id;
$signature->uuid = Str::uuid();
$signature->filename = $imageName;
$signature->document_filename = null;
$signature->certified = false;
$signature->from_ips = json_encode([request()->ip()]);
$signature->save();
// Redirect back with success message.
return redirect()->back()->with('success', 'Employment Agreement submited successfully!');
}
public function show(User $user)
{
// Load the user's signature relationship.
$user->load('signature');
// Return the view to display the user's details and signature.
return view('show', compact('user'));
}
}
Step # 8 : Create a storage link.
Run the command to create a symbolic link from the public directory to the storage directory.Command: php artisan storage:link
Step # 9 : Create Views.
Create a view named sign.blade.php that contains a form for creating a user with an employment agreement.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Shotcut - Employment Agreement</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.sign-pad-button-submit {
margin-top: 5px;
background-color: #3b82f6;
color: white;
font-weight: bold;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: background-color 0.3s ease;
}
.sign-pad-button-submit:hover {
background-color: #2563eb;
}
.sign-pad-button-clear {
margin-top: 5px;
background-color: #ef4444;
color: white;
font-weight: bold;
padding: 0.5rem 1rem;
border-radius: 0.5rem;
transition: background-color 0.3s ease;
}
.sign-pad-button-clear:hover {
background-color: #dc2626;
}
</style>
</head>
<body class="bg-gray-50 min-h-screen flex items-center justify-center">
<form action="/confirm" method="POST" class="bg-white p-10 rounded-lg shadow-lg max-w-xl w-full">
@csrf
<h1 class="text-2xl font-bold text-center mb-4">Code Shotcut - Employment Agreement</h1>
<p class="mb-4 text-justify text-gray-600">
Please fill in your details and sign below to confirm your acceptance of the employment terms.
</p>
<!-- Display Success Message -->
@if (session('success'))
<div class="bg-green-100 text-green-700 p-4 rounded mb-4">
{{ session('success') }}
</div>
@endif
<!-- Display Error Messages -->
@if ($errors->any())
<div class="bg-red-100 text-red-700 p-4 rounded mb-4">
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="mb-4">
<label for="name" class="block text-lg text-gray-700 font-medium mb-1">Full Name</label>
<input type="text" id="name" name="name"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Enter your full name" required />
</div>
<div class="mb-4">
<label for="email" class="block text-lg text-gray-700 font-medium mb-1">Email Address</label>
<input type="email" id="email" name="email"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Enter your email" required />
</div>
<div class="mb-4">
<label for="password" class="block text-lg text-gray-700 font-medium mb-1">Password</label>
<input type="password" id="password" name="password"
class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
placeholder="Create a password" required />
</div>
<!-- Signature Pad -->
<div class="mb-4">
<label class="block text-lg text-gray-700 font-medium mb-2">Signature</label>
<x-creagia-signature-pad name='sign' />
</div>
</form>
<!-- Sign-pad js -->
<script src="{{ asset('vendor/sign-pad/sign-pad.min.js') }}"></script>
</body>
</html>
Create an additional view named show.blade.php to display the user's agreement details.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Code Shotcut - User Agreement</title>
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gray-50 min-h-screen flex items-center justify-center">
<div class="bg-white p-10 rounded-lg shadow-lg max-w-md w-full">
<h1 class="text-2xl font-bold text-center mb-4">User Details</h1>
<p><strong>Name:</strong> {{ $user->name }}</p>
<p><strong>Email:</strong> {{ $user->email }}</p>
<h2 class="mt-4 mb-2 text-lg font-medium">Signature</h2>
@if ($user->signature)
<img src="{{ asset('storage/' . $user->signature->filename) }}" alt="User Signature" class="w-full h-auto">
@else
<p>No signature available.</p>
@endif
</div>
</body>
</html>
Step # 10 : It's time to test.
Start the Laravel development server.
Command : php artisan serve.
Open your web browser and navigate to the following URL.
127.0.0.1:8000
Complete the form and submit it.
To view the agreement, use the following link, replacing $id with the appropriate user ID
127/0.0.1/show/$id
For more details please refer to the package documentation.
Share this with friends!
To engage in commentary, kindly proceed by logging in or registering
Subscribe to Our Newsletter
Stay ahead of the curve! Join our newsletter to see what everyone’s talking about.
0 Comments