In this article we’ll create dependent dropdown / dynamic select menu using Axios and pure JS in Laravel 9. For this article we’ll utilize the models and data created in a previous article. So, first follow the steps given there for creating models, migrations, and relationship and then continue from here.
By following the above-mentioned article, we now have a couple of tables (customers and invoices) having one-to-many relationship along with test data; so, let’s move onto controller. Execute following command in parent folder to create InvoiceController.php;
php artisan make:controller InvoiceController
Then, open app/Http/Controllers/InvoiceController.php and amend it as follows;
<?php
namespace App\Http\Controllers;
use Illuminate\Support\Facades\DB;
class InvoiceController extends Controller
{
public function select()
{
return view('select');
}
public function findInvoices($id)
{
$invoices = DB::table('invoices')
->where('customer_id', '=', $id)
->get();
return response()->json($invoices);
}
public function showInvoice($id)
{
$invoice = collect(DB::table('customers')
->join('invoices', 'customers.id', '=', 'invoices.customer_id')
->where('invoices.id', '=', $id)
->select('invoices.*', 'customers.name', 'customers.address')
->first());
return response()->json($invoice);
}
}
Next, open routes/web.php and put the following line at the upper side of it;
use App\Http\Controllers\InvoiceController;
And then insert following routes inside this routes/web.php;
Route::get('/select', [InvoiceController::class, 'select']);
Route::get('/findInvoices/{id}', [InvoiceController::class, 'findInvoices']);
Route::get('/showInvoice/{id}', [InvoiceController::class, 'showInvoice']);
Now let’s move onto View side of action. We’ll keep things bare-bones in this article by employing default Blade template along with pure Javascript and Axios. It’s worth noting here that Laravel 9 incorporates Axios by default as development dependency along with Vite as build tool; means, we just have to execute ‘npm install‘ and ‘npm run build‘ in order to have Axios available to Blade templates. So, let’s run both the commands in parent folder in single line;
npm install && npm run build
Wait till npm modules are installed and Vite build process is finished. Then, create select.blade.php inside resources/views folder. You can execute following command inside parent folder to create this file;
touch resources/views/select.blade.php
Then, insert following code inside resources/views/select.blade.php;
<!DOCTYPE html>
<html>
<head>
<title>Select</title>
@vite(['resources/js/app.js'])
<style>
div {margin: 10px;}
label {width: 100px; display: inline-block;}
select {width: 200px;}
table {border: 1px solid black; border-collapse: collapse; margin: 10px;}
</style>
</head>
<body>
<div>
<div>
<label for="customer">Customer:</label>
<select class="" name="customer" id="customer" onchange="customerChange(event)">
<option value="">Select Customer here</option>
@foreach (App\Models\Customer::all() as $item)
<option value="{{$item->id}}">{{$item->name}}</option>
@endforeach
</select>
</div>
<div>
<label for="invoice">Invoices:</label>
<select class="" id="invoice" name="invoice" onchange="invoiceChange(event)">
<option value=''>Please choose customer first</option>
</select>
</div>
</div>
<div>
<table id="t1"></table>
</div>
<script>
function customerChange(e) {
axios.get('/findInvoices/'+e.target.value).then(res => {
document.getElementById("invoice").options.length = 0;
document.getElementById("invoice").add(new Option('Now select invoice', ''));
let d = res.data;
for(let x in d)
document.getElementById("invoice").add(new Option(d[x].invoice_number, d[x].id));
});
}
function invoiceChange(e) {
axios.get('/showInvoice/'+e.target.value).then(res => {
let d = res.data;
document.getElementById("t1").innerHTML = "<tr><td>Reference:</td><td>"+d.invoice_number+"</td></tr><tr><td>Date of invoice:</td><td>"+d.invoice_date+"</td></tr><tr><td>Customer:</td><td>"+d.name+"</td></tr><tr><td>Address:</td><td>"+d.address+"</td></tr><tr><td>Invoice Description:</td><td>"+d.description+"</td></tr><tr><td>Amount:</td><td>"+d.amount+"</td></tr>";
});
}
</script>
</body>
</html>
Run PHP development server;
php artisan serv
Finally, enter following URL in the browser;
http://localhost:8000/select