ببض الإحيان نحتاج لجلب معلومات من قاعدة البيانات ووضعها في dropdown list، لكن بناءً على نتيجة إختيار حقل أخر، مثلا لفرض أن لدينا dropdown menu بها الدول، فعندما يقوم المستخدم بإختيار دولة مثلا (فلسطين)، أن تظهر جميع المدن التابعة لهذه الدولة ( المدن الفلسطينية )، وهكذا.
الخطوات
إنشاء Category Model مع ملف migration
php artisan make:model Category -m
تحديد الحقول في ملف migration
Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->unsignedInteger('parent_id')->nullable(); $table->timestamps(); });
نلاحظ هنا، أنه تم إستخدام حقل parent_id، حيث إسم الدولة سيأخذ قيمة 0، والمدن ستأخذ id الدولة التابعة لها.
إنشاء Category Controller
php artisan make:controller CategoryController
إنشاء route في ملف web.php
Route::get('cat', [CategoryController::class, 'index']);
بداخل CategoryController ننشئ الدالة index حيث بها سيتم إستخراج جميع الأقسام التي لها parent_id=0
public function index(Request $request) { $categoris = Category::where('parent_id',0)->get(); return view('category',["categoris" => $categoris]); }
في الملف category.blade.php نقوم بعرض الـ categoris في dropdown، وكذلك ننشئ dropdown للمدن، لكن تكون فارغه اي دون option
كذلك يجب تضمين مكتبة jquery و تحديد csrt-token في head لأننا سوف نستخدم الطلب POST بإستخدام ajax
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <meta name="csrf-token" content="{{ csrf_token() }}" />
<form action=""> <h4>Category</h4> <select class="browser-default custom-select" name="category" id="category"> <option selected>Select category</option> @foreach ($categoris as $item) <option value="{{ $item->id }}">{{ $item->name }}</option> @endforeach </select> <h4>Subcategory</h4> <select class="browser-default custom-select" name="subcategory" id="subcategory"> </select> </form>
ما يهمنا هنا، أنه تم إعطاء الـ dropdown الخاص بالدول id=category والـ dropdown االخاصه بالمدن id=subcategory لأن هذا ما سنتعامل معه في jquery.
كتابة كود ajax
<script type="text/javascript"> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $(document).ready(function () { $('#category').on('change',function(e) { var cat_id = e.target.value; $.ajax({ url:"{{ route('subcat') }}", type:"POST", data: { cat_id: cat_id }, beforeSend: function () { $('#subcategory').html('<img src="/admin/img/loading.gif">'); }, success:function (data) { $('#subcategory').empty(); $.each(data.subcategories[0].subcategories,function(index,subcategory){ $('#subcategory').append('<option value="'+subcategory.id+'">'+subcategory.name+'</option>'); }) } }) }); }); </script>
إنشاء route بإسم subcat
Route::post('subcat', [CategoryController::class, 'subCat'])->name('subcat');
إنشاء دالة subCat بداخل CategoryController
public function subCat(Request $request) { $parent_id = $request->cat_id; $subcategories = Category::where('id',$parent_id) ->with('subcategories') ->get(); return response()->json([ 'subcategories' => $subcategories ]); }
كما نلاحظ ان البيانات يتم إرجاعها على شكل json
route
Route::get('cat', [CategoryController::class, 'index']); Route::post('subcat', [CategoryController::class, 'subCat'])->name('subcat');
Migration
public function up() { Schema::create('categories', function (Blueprint $table) { $table->id(); $table->string('name'); $table->unsignedInteger('parent_id')->nullable(); $table->timestamps(); }); }
Category Model
class Category extends Model { use HasFactory; public function subcategories(){ return $this->hasMany('App\Models\Category', 'parent_id'); } }
CategoryController
class CategoryController extends Controller { public function index(Request $request) { $categoris = Category::where('parent_id',0)->get(); return view('category',["categoris" => $categoris]); } public function subCat(Request $request) { $parent_id = $request->cat_id; $subcategories = Category::where('id',$parent_id) ->with('subcategories') ->get(); return response()->json([ 'subcategories' => $subcategories ]); } }
Category.blade.php
<html lang="{{ app()->getLocale() }}"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Laravel 8 jquery ajax categories and subcategories, select dropdown</title> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"> <meta name="csrf-token" content="{{ csrf_token() }}" /> </head> <body> <div class="container" style="margin-top: 50px; margin-left: 300px"> <div class="row"> <div class="col-lg-6"> <form action=""> <h4>Category</h4> <select class="browser-default custom-select" name="category" id="category"> <option selected>Select category</option> @foreach ($categoris as $item) <option value="{{ $item->id }}">{{ $item->name }}</option> @endforeach </select> <h4>Subcategory</h4> <select class="browser-default custom-select" name="subcategory" id="subcategory"> </select> </form> </div> </div> </div> <script type="text/javascript"> $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') } }); $(document).ready(function () { $('#category').on('change',function(e) { var cat_id = e.target.value; $.ajax({ url:"{{ route('subcat') }}", type:"POST", data: { cat_id: cat_id }, beforeSend: function () { $('#subcategory').html('<img src="/admin/img/loading.gif">'); }, success:function (data) { $('#subcategory').empty(); $.each(data.subcategories[0].subcategories,function(index,subcategory){ $('#subcategory').append('<option value="'+subcategory.id+'">'+subcategory.name+'</option>'); }) } }) }); }); </script> </body> </html>