My appreciation for form API in Drupal is on the same level as my attempt to avoid it when it comes to user facing forms. Both are pretty high. The reasons I love it are because it’s extendible and security is built in. I’ve worked with a few other frameworks in different languages, and my impression is that Drupal’s form API is significantly more advanced than any other solution I’ve seen.

The reason I try to avoid it, on the other hand, is mainly because it’s hard to create forms that satisfy the end users, and achieve their expectations. Basically, forms are bulky, and going with a mix of JS/Ajaxy solutions is often a pain. Having a JS form (i.e. some JS widget that builds and controls the entire form), that POSTs to a RESTful endpoint takes more code, but often times provides a more streamlined user experience.

Not sure why and how, but over the years we’ve been tasked quite a few times with creating form wizards. It’s frequently used for more complex registrations, like for students, or alumnus applying for different programs. In the early Drupal 7 days we went with CTools’ wizard, and then switched to Elm (i.e. a JS form) along with RESTful endpoints. Drupal 8 however has one major feature that makes it very appealing to work once more with form API - that is “Form modes.”

This post has an example repo, that you should be able to reliably download and run locally thanks to DDEV. I will not try to cover every single line of code - but rather share the concepts behind our implementation, with some references to the code. The audience is intermediate-level Drupal developers, that can expect to have a good sense of how to use Form modes to build wizards after reading this post and going over the code.

Before diving in, it’s important to recognize that “wizards” come in many flavors. I personally hold the opinion that a generic module cannot be (easily) built to accommodate all cases. Instead, I look at Drupal 8 with its core and a couple of contrib modules as the “generic” solution to build complex - sprinkled with lots of custom business logic - wizards.