لارافيل, JQuery / 2024-05-15

طريقة عمل Dynamic Dependent Dropdown بإستخدام لارافيل و ajax

طريقة عمل Dynamic Dependent Dropdown بإستخدام لارافيل و ajax

2024-05-15 وقت القراءه : 5 دقائق

ببض الإحيان نحتاج لجلب معلومات من قاعدة البيانات ووضعها في 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>
  • بداية يجب إرسال x-csrf-token.
  • عند تغيير حالة #category أي عندما يختار المستخدم دولة معينة، فإنه سيتم إنشاء طلب ajax مع نوع post على الـ route المحدد وهو بإسم subcat.
  • عند تغيير حالة #category سيتم أخذ قيمة هذا الـ #، وضعه في متغيرر cat_id، وهو ما سيتم إرسالة في الـ route.
  • تم إستخدام الدالة beforeSend لعرض صوره loading لحين جلب البيانات وعرضها.
  • تم إستخدام الدالة complete لإخفاء الصوره التي تم عرضها عند إكتمال جلب البيانات.
  • عند نجاح الإتصال، سيتم تفريغ الـ #subcategory من البيانات.
  • البيانات التي تأتي من السيرفر، سيتم وضعها في متغير data، حيث قمنا بتحديد ذلك success:function(data)، وسيتم عمل each بمعنى loop وفي كل مره سيتم عمل append لهذه البيانات وعرضها في #subcategory.


إنشاء 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>



إضافة تعليق
Loading...