Multi-Step Form with Vue.js, Inertia and Laravel Breeze

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...

The full tutorial [21 mins, 4103 words] is only for Premium Members

Login Or Become a Premium Member for $129/year or $29/month
What else you will get:
  • 68 courses (1188 lessons, total 43 h 18 min)
  • 90 long-form tutorials (one new every week)
  • access to project repositories
  • access to private Discord

Recent New Courses