webdevpuneet.com

SweetAlert2 Multi-Step Input Flow — Free HTML CSS JS Snippet

SweetAlert2 Multi-Step Input Flow · Modals · Plain HTML, CSS & JS · Live preview

CategoryModals

Copy & paste

Source Code

<div class="ms-wrap">
  <button class="ms-btn" id="msStart" type="button">Create New Project</button>
  <div class="ms-log" id="msLog">No project created yet</div>
</div>

Extend with AI

Take This Snippet Further With AI

The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.

· Become a supporter

What's included

Features

Shared step configuration
Swal.mixin applies common settings to every step at once.
Modern promise-chain pattern
The documented replacement for the removed Swal.queue().
Per-step validation
Each step blocks advancing until its own input is valid.
Visual progress indicator
currentProgressStep highlights the correct dot per step.
Correct cancel-anywhere behavior
isConfirmed checks stop the chain cleanly at any step.
Accidental-dismissal protection
Outside clicks cannot silently discard a multi-step flow.

About this UI Snippet

SweetAlert2 Multi-Step Input Flow — Chaining Promises Where queue() Used to Be

Screenshot of the SweetAlert2 Multi-Step Input Flow snippet rendered live

Older SweetAlert2 versions had a built-in Swal.queue() helper for exactly this — a linear sequence of steps with a shared progress indicator. SweetAlert2 v11 removed it, and the current documented approach is a plain chain of Swal.fire() calls, each one only firing after the previous step's promise resolves, with your own code threading the collected answers through the chain.

Swal.mixin factors out what every step shares

Swal.mixin({...}) creates a reusable dialog config — progressSteps, button colors, cancel behavior — applied automatically to every StepSwal.fire() call, instead of repeating those five settings three separate times. Each individual step's fire() call only needs to specify what's actually different about that step: its title, its input type, and its validator.

currentProgressStep drives which dot is highlighted

Setting currentProgressStep: 1 on the second step's config is what tells SweetAlert2's built-in progress-steps indicator which of the three dots to show as current — this is purely a display setting per call, independent of the actual chaining logic that moves between steps.

Chained .then() calls, not a queue array

Each step's .then() callback checks isConfirmed, saves that step's value onto a shared answers object, and returns the *next* StepSwal.fire() call — returning a Promise from inside a .then() is what chains it, ensuring step 3 never fires until step 2's promise has actually resolved. Any step's Cancel button resolves with isConfirmed: false, and every .then() checks that before proceeding — cancelling at step 2 correctly stops the flow rather than skipping ahead to step 3.

inputValidator blocks advancing on each step independently

Every step declares its own inputValidator function, returning an error string (which SweetAlert2 displays inline and refuses to advance past) when a value is missing — the project name step requires non-empty text, the template and visibility steps require an option to be picked, each validated the moment "Next" is clicked on that specific step.

allowOutsideClick: false keeps a multi-step flow from vanishing accidentally

A single confirmation dialog closing on an accidental outside click is a minor annoyance; losing the last two minutes of a multi-step form to the same accident is worse. Disabling outside-click dismissal (kept in the shared Swal.mixin) means the only ways out of the flow are the explicit Next/Cancel buttons.

Reusing it

Add a fourth step by inserting one more StepSwal.fire(...).then(...) link in the chain (bumping progressSteps and every later currentProgressStep value) — the pattern scales to any number of sequential steps.

Step by step

How to Use

  1. 1
    Add the SweetAlert2 CDNLoad sweetalert2.all.min.js before the snippet's JS runs.
  2. 2
    Paste HTML, CSS, and JSA "Create New Project" button renders.
  3. 3
    Click the buttonStep 1 of 3 opens asking for a project name.
  4. 4
    Try clicking Next with an empty nameAn inline validation error appears, blocking advance.
  5. 5
    Complete all three stepsA success dialog confirms, and details log below.
  6. 6
    Click Cancel on any stepThe flow stops immediately with nothing created.

Real-world uses

Common Use Cases

Project creation wizards
Collect project details across three chained dialogs, using Swal.mixin so common settings apply to every step at once.
Onboarding and account setup
Gather onboarding and account setup data step by step, with each step blocked by its own inputValidator until the input is valid.
Checkout configuration
Pair with the SweetAlert2 confirmation dialog set so a configured order ends in a clear final confirmation.
Survey and feedback collection
Ask sequential questions without leaving the page, with currentProgressStep highlighting the correct dot at each stage.
Replacing the removed queue API
Learn the modern promise-chain pattern that replaced the removed Swal.queue() helper, as documented for SweetAlert2 version 11 and later.

Got questions?

Frequently Asked Questions

Swal.queue() was a built-in helper in older SweetAlert2 versions for running a linear sequence of dialogs, but it was removed in SweetAlert2 v11. The currently documented approach for multi-step flows is chaining plain Swal.fire() calls: each step's .then() callback returns the next step's Swal.fire() call, which is what makes the following .then() wait for it, with a shared object threaded manually through the chain to collect each step's answer.

Swal.mixin({...}) creates a version of Swal pre-configured with certain default options — in this case, the shared progress-steps indicator, button colors, and cancel behavior — so every call to StepSwal.fire() automatically includes those settings without repeating them. Each individual step then only needs to specify what's actually unique about it, like its title and input type.

Every step's .then() callback checks result.isConfirmed before doing anything else, and returns immediately (without calling the next step's Swal.fire()) if it's false. Since isConfirmed is false whenever the cancel button, an outside click, or Escape closes a dialog, cancelling at any step correctly halts the chain right there — the code never reaches the line that would fire the next step.

Each step's Swal.fire() call includes a currentProgressStep value (0 for the first step, 1 for the second, and so on), which SweetAlert2's built-in progress-steps display reads to determine which dot to highlight as the current step. This is a purely visual setting, separate from the actual promise-chaining logic that determines when to move to the next step.

Add a new '4' entry to the progressSteps array in Swal.mixin, then insert another StepSwal.fire({ ..., currentProgressStep: 3 }).then(function (step4) { ... }) link into the promise chain between the existing steps (or after the last one), following the same isConfirmed-check-then-save-then-return-next-step pattern the existing three steps already use.