Динамичные select в форме (Laravel + jQuery)

Динамичные select в форме (Laravel + jQuery)

Предположим у нас следующая задача: Необходимо сделать простую форму для выбора стран и городов. В форме имеются два поля выбора (select), в первом выбирается страна, а во втором города и в зависимости от выбранной страны города будут разные.

Мы будем работать в фреймворке Laravel. Предполагается, что у вас уже создана БД и в файле .env указаны необходимые настройки к ее подключению.

Создаем модели и миграции

Нам понадобятся две таблицы:

  • Страны
  • Города

Создаем две модели Country и City:

php artisan make:model Country -m

php artisan make:model City -m

Мы добавили флаг -m, чтобы одновременно создалась миграция.

Далее идем в папку миграций (database/migrations) и правим в них функцию up().

Вот так выглядит функция up() в миграции create_countries_table:

public function up()
    {
        Schema::create('countries', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->timestamps();
        });
    }

Вот так выглядит функция up() в миграции create_cities_table:

public function up()
    {
        Schema::create('cities', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('name');
            $table->unsignedInteger('id_country');
            $table->timestamps();
        });
    }

Далее выполняем миграцию:

php artisan migrate

После создания таблиц Страны и Города, их необходимо заполнить тестовыми данными для дальнейшей работы.

Динамичные select в форме (Laravel + jQuery)

Создаем контроллер

Далее создаем контроллер, назовем его CountryController, для этого выполним команду:

php artisan make:controller CountryController

Идем в контроллер (app/Http/Controllers/CountryController.php) и создаем функцию index() с помощью нее мы будем выводить нашу форму с динамическими полями select.

А так же функцию selectCity() с помощью которой мы будем обрабатывать ajax запросы из формы и возвращать список городов для определенной страны.

В конечном счете контроллер должен выглядеть так:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Country;
use App\City;

class CountryController extends Controller
{
    public function index()
    {
        $countries = Country::all();
        return view('country_form', ['countries' => $countries]);
    }

    public function selectCity(Request $request){
        if($request->ajax()){
            $cities = City::where('id_country',$request->id_country)->get()->pluck("name","id");
            $data = view('selectcity',['cities' => $cities])->render();
            return response()->json(['options'=>$data]);
        }
    }
}

Создание шаблонов

Пора создать шаблоны. Первый шаблон resources/views/country_form.blade.php очень простой, сделаем его на основе стартового шаблона Bootstrap 4 (https://getbootstrap.com/docs/4.5/getting-started/introduction/#starter-template), в нем содержится только форма с двумя select полями.

<!doctype html>
<html lang="ru">
<head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
    <title>Динамический select в Laravel</title>
</head>
<body>

<div class="container">
    <h1>Динамический select в Laravel</h1>
    <form>
        @csrf
        <div class="form-group">
            <label for="countries">Страна</label>
            <select class="form-control" id="countries">
                <option>Выберите страну</option>
                @foreach($countries as $country)
                    <option value="{{ $country->id }}">{{ $country->name }}</option>
                @endforeach
            </select>
        </div>

        <div class="form-group">
            <label for="city">Город</label>
            <select class="form-control" id="city">
                <option>Выберите город</option>
            </select>
        </div>

    </form>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js"></script>

<script type="text/javascript">
    $("#countries").change(function(){
        var id_country = $(this).val();
        var token = $("input[name='_token']").val();
        console.log(id_country);

        $.ajax({
            url: "{{ route('selectcity') }}",
            method: 'POST',
            data: {id_country:id_country, _token:token},
            success: function(data) {
                $("#city").html('');
                $("#city").html(data.options);
            }
        });
    });
</script>

</body>
</html>

Создадим следующий шаблон resources/views/selectcity.blade.php, который будет формировать список options для selecta выбора города и будет подгружаться в форму основного шаблона шаблон country_form.blade.php

<option>Выберите город</option>
@if(!empty($cities))
    @foreach($cities as $key => $value)
        <option value="{{ $key }}">{{ $value }}</option>
    @endforeach
@endif

Завершающий этап

Не забудем добавить роуты, идем в routes/web.php и дописываем:

Route::get('countryform', 'CountryController@index');
Route::post('selectcity', 'CountryController@selectCity')->name('selectcity');

Теперь все должно работать, идем по адресу нашей формы, в моем случае http://laratest.loc/countryform и проверяем:

Динамичные select в форме (Laravel + jQuery)

Отлично, работает!

Хостинг для ваших проектов