Multi Step Registration Form In Flutter With/Without Provider

Desi ProgrammerDesi Programmer
4 min read

We will create a multi-step registration form using Flutter in two ways.

  1. Using the simple basic setstate and Widgets.

  2. Using a provider.

Watch Tutorial

%[https://www.youtube.com/watch?v=uc5-nl3G9ew]

With Basic Widgets

import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:im_stepper/stepper.dart';

class MultiPageBasic extends StatefulWidget {
  const MultiPageBasic({Key? key}) : super(key: key);

  @override
  _MultiPageBasicState createState() => _MultiPageBasicState();
}

class _MultiPageBasicState extends State<MultiPageBasic> {
  //
  GlobalKey<FormState> basicFormKey = GlobalKey<FormState>();

  int activeIndex = 0;
  int totalIndex = 2;

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        if (activeIndex != 0) {
          activeIndex--;
          setState(() {});
          return false;
        }
        return true;
      },
      child: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Basic Multi Step",
          ),
        ),
        //
        body: bodyBuilder(),
      ),
    );
  }

  Widget bodyBuilder() {
    switch (activeIndex) {
      case 0:
        return basicDetails();
      case 1:
        return educationDetails();

      default:
        return basicDetails();
    }
  }

  Widget basicDetails() {
    return Form(
      key: basicFormKey,
      child: ListView(
        padding: const EdgeInsets.all(
          12.0,
        ),
        children: [
          Center(
            child: DotStepper(
              activeStep: activeIndex,
              dotRadius: 20.0,
              shape: Shape.pipe,
              spacing: 10.0,
            ),
          ),
          Text(
            "Step ${activeIndex + 1} of $totalIndex",
            style: const TextStyle(
              fontSize: 20.0,
            ),
            textAlign: TextAlign.center,
          ),
          TextFormField(
            decoration: const InputDecoration(
              labelText: "Name",
            ),
            validator: RequiredValidator(
              errorText: "Required *",
            ),
          ),
          TextFormField(
              decoration: const InputDecoration(
                labelText: "Email",
              ),
              validator: MultiValidator([
                RequiredValidator(
                  errorText: "Required *",
                ),
                EmailValidator(
                  errorText: "Not Valid Email",
                ),
              ])),
          TextFormField(
            decoration: const InputDecoration(
              labelText: "Passoword",
            ),
            validator: MinLengthValidator(
              6,
              errorText: "Min 6 characters required",
            ),
          ),
          const SizedBox(
            height: 12.0,
          ),
          SizedBox(
            height: 40.0,
            child: ElevatedButton(
              onPressed: () {
                if (basicFormKey.currentState?.validate() ?? false) {
                  // next
                  setState(() {
                    activeIndex++;
                  });
                }
              },
              child: const Text(
                "Next",
                style: TextStyle(
                  fontSize: 20.0,
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget educationDetails() {
    return ListView(
      padding: const EdgeInsets.all(
        12.0,
      ),
      children: [
        Center(
          child: DotStepper(
            activeStep: activeIndex,
            dotRadius: 20.0,
            shape: Shape.pipe,
            spacing: 10.0,
          ),
        ),
        Text(
          "Step ${activeIndex + 1} of $totalIndex",
          style: const TextStyle(
            fontSize: 20.0,
          ),
          textAlign: TextAlign.center,
        ),
        TextFormField(
          decoration: const InputDecoration(
            labelText: "Name",
          ),
          validator: RequiredValidator(
            errorText: "Required *",
          ),
        ),
        const SizedBox(
          height: 12.0,
        ),
        SizedBox(
          height: 40.0,
          child: ElevatedButton(
            onPressed: () {},
            child: const Text(
              "Register",
              style: TextStyle(
                fontSize: 20.0,
              ),
            ),
          ),
        ),
      ],
    );
  }
}

Using Provider

I will be using provider to easily pass data in widget tree.

  1. Add this to pubspec.yaml file.
provider: ^6.0.2
  1. Add the user modal
import 'package:flutter/foundation.dart';

class UserModal extends ChangeNotifier {
  String? name;
  String? email;
  String? password;
  String? education;

  int activeIndex = 0;
  int totalIndex = 2;

  changeStep(int index) {
    activeIndex = index;
    notifyListeners();
  }
}
  1. And The final Code for the Page.
import 'package:flutter/material.dart';
import 'package:form_field_validator/form_field_validator.dart';
import 'package:im_stepper/stepper.dart';
import 'package:multi_step_form/modal/user_modal.dart';
import 'package:provider/provider.dart';

class MultiPageProvider extends StatefulWidget {
  const MultiPageProvider({Key? key}) : super(key: key);

  @override
  _MultiPageProviderState createState() => _MultiPageProviderState();
}

class _MultiPageProviderState extends State<MultiPageProvider> {
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<UserModal>(
      create: (context) => UserModal(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text(
            "Using Provider",
          ),
        ),
        body: Consumer<UserModal>(
          builder: (context, modal, child) {
            switch (modal.activeIndex) {
              case 0:
                return const BasicDetails();
              case 1:
                return const EducationDetails();

              default:
                return const BasicDetails();
            }
          },
        ),
      ),
    );
  }
}

class BasicDetails extends StatefulWidget {
  const BasicDetails({Key? key}) : super(key: key);

  @override
  _BasicDetailsState createState() => _BasicDetailsState();
}

class _BasicDetailsState extends State<BasicDetails> {
  GlobalKey<FormState> basicFormKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Consumer<UserModal>(builder: (context, modal, child) {
      return Form(
        key: basicFormKey,
        child: ListView(
          padding: const EdgeInsets.all(
            12.0,
          ),
          children: [
            Center(
              child: DotStepper(
                activeStep: modal.activeIndex,
                dotRadius: 20.0,
                shape: Shape.pipe,
                spacing: 10.0,
              ),
            ),
            Text(
              "Step ${modal.activeIndex + 1} of ${modal.totalIndex}",
              style: const TextStyle(
                fontSize: 20.0,
              ),
              textAlign: TextAlign.center,
            ),
            TextFormField(
              decoration: const InputDecoration(
                labelText: "Name",
              ),
              validator: RequiredValidator(
                errorText: "Required *",
              ),
            ),
            TextFormField(
                decoration: const InputDecoration(
                  labelText: "Email",
                ),
                validator: MultiValidator([
                  RequiredValidator(
                    errorText: "Required *",
                  ),
                  EmailValidator(
                    errorText: "Not Valid Email",
                  ),
                ])),
            TextFormField(
              decoration: const InputDecoration(
                labelText: "Passoword",
              ),
              validator: MinLengthValidator(
                6,
                errorText: "Min 6 characters required",
              ),
            ),
            const SizedBox(
              height: 12.0,
            ),
            SizedBox(
              height: 40.0,
              child: ElevatedButton(
                onPressed: () {
                  if (basicFormKey.currentState?.validate() ?? false) {
                    // next
                    modal.changeStep(1);
                  }
                },
                child: const Text(
                  "Next",
                  style: TextStyle(
                    fontSize: 20.0,
                  ),
                ),
              ),
            ),
          ],
        ),
      );
    });
  }
}

class EducationDetails extends StatelessWidget {
  const EducationDetails({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Consumer<UserModal>(builder: (context, modal, child) {
      return ListView(
        padding: const EdgeInsets.all(
          12.0,
        ),
        children: [
          Center(
            child: DotStepper(
              activeStep: modal.activeIndex,
              dotRadius: 20.0,
              shape: Shape.pipe,
              spacing: 10.0,
            ),
          ),
          Text(
            "Step ${modal.activeIndex + 1} of ${modal.totalIndex}",
            style: const TextStyle(
              fontSize: 20.0,
            ),
            textAlign: TextAlign.center,
          ),
          TextFormField(
            decoration: const InputDecoration(
              labelText: "Name",
            ),
            validator: RequiredValidator(
              errorText: "Required *",
            ),
          ),
          const SizedBox(
            height: 12.0,
          ),
          SizedBox(
            height: 40.0,
            child: ElevatedButton(
              onPressed: () {},
              child: const Text(
                "Register",
                style: TextStyle(
                  fontSize: 20.0,
                ),
              ),
            ),
          ),
        ],
      );
    });
  }
}
0
Subscribe to my newsletter

Read articles from Desi Programmer directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Desi Programmer
Desi Programmer

As a YouTube content creator, I specialize in producing high-quality videos related to cutting-edge technologies and frameworks. My areas of expertise include Flutter, Express.js, Laravel, React JS, Angular, .Net , Native Android and iOS development, Django, Tkinter and Full Stack Development. Whether you're a beginner or an advanced user, my videos are designed to help you stay up-to-date with the latest trends and techniques in the field. Join me on my channel to discover new ways to expand your skills and take your projects to the next level.