If you have a form with 10+ fields, it may make sense to divide them into multiple steps. Let me show you how to do it in Vue.js with Inertia.
In this tutorial, we will build a simple three-step form using Vue.js for the front-end and Inertia to glue with Laravel as a back-end. Link to the repository is included at the end of the tutorial.
Initial Laravel Project
We will use Breeze starter kit only for quick Inertia installation.
First, we need to see what the initial Laravel project looks like. Below, you will see the migrations and models.
database/migrations/xxx_create_countries_table.php:
Schema::create('countries', function (Blueprint $table) { $table->id(); $table->string('name'); $table->timestamps();});
database/migrations/xxx_create_cities_table.php:
Schema::create('cities', function (Blueprint $table) { $table->id(); $table->foreignId('country_id'); $table->string('name'); $table->decimal('adult_price'); $table->decimal('children_price'); $table->timestamps();});
app/Models/Country.php:
class Country extends Model{ protected $fillable = [ 'name', ];}
app/Models/City.php:
class City extends Model{ protected $fillable = [ 'country_id', 'name', 'adult_price', 'child_price', ];}
We have a seeder to add some data to have data for select inputs and calculating the price after submitting a form.
database/seeders/DatabaseSeeder.php:
use App\Models\User;use App\Models\City;use App\Models\Country;use Illuminate\Database\Seeder; class DatabaseSeeder extends Seeder{ public function run(): void { Country::create(['name' => 'United States']); Country::create(['name' => 'United Kingdom']); Country::create(['name' => 'Germany']); City::create(['country_id' => 1, 'name' => 'New York', 'adult_price' => 100, 'children_price' => 75]); City::create(['country_id' => 1, 'name' => 'Washington', 'adult_price' => 150, 'children_price' => 100]); City::create(['country_id' => 2, 'name' => 'London', 'adult_price' => 200, 'children_price' => 175]); City::create(['country_id' => 2, 'name' => 'Birmingham', 'adult_price' => 250, 'children_price' => 195]); City::create(['country_id' => 3, 'name' => 'Berlin', 'adult_price' => 125, 'children_price' => 85]); City::create(['country_id' => 3, 'name' => 'Stuttgart', 'adult_price' => 190, 'children_price' => 155]); }}
Remember to run
npm run dev
; otherwise, you won't see any changes on the front end.
Initial Multi-Step Form
First, let's create a form. For simplicity, we will add the form to the Dashboard.vue
Vue component. For that, we need to change the route to use a Controller. In the Controller, we will return an Inertia response and pass countries with cities.
php artisan make:controller MultiStepController
app/Http/Controllers/MultiStepController.php:
use Inertia\Inertia;use App\Models\City;use Inertia\Response;use App\Models\Country; class MultiStepController extends Controller{ public function index(): Response { return Inertia::render('Dashboard', [ 'countries' => Country::all()->toArray(), 'cities' => City::all()->groupBy('country_id')->toArray(), ]); }}
routes/web.php:
use App\Http\Controllers\MultiStepController; // ... Route::get('/dashboard', function () { return Inertia::render('Dashboard');})->middleware(['auth', 'verified'])->name('dashboard');Route::get('/dashboard', [MultiStepController::class, 'index'])->middleware(['auth', 'verified'])->name('dashboard'); // ...
In the Vue component, we use a simple...