Multi Step Registration Form In Flutter With/Without Provider
Table of contents
We will create a multi-step registration form using Flutter in two ways.
Using the simple basic setstate and Widgets.
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.
- Add this to
pubspec.yaml
file.
provider: ^6.0.2
- 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();
}
}
- 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,
),
),
),
),
],
);
});
}
}
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.