Skip to content

Instantly share code, notes, and snippets.

@Sominemo
Last active November 23, 2022 11:28
Show Gist options
  • Save Sominemo/bd54353375c38ccc349116bdbe39c05e to your computer and use it in GitHub Desktop.
Save Sominemo/bd54353375c38ccc349116bdbe39c05e to your computer and use it in GitHub Desktop.
Flutter password validation bullet list example
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Password Check'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: const Form(child: PasswordValidationFormContent()),
);
}
}
class PasswordValidationFormContent extends StatefulWidget {
const PasswordValidationFormContent({super.key});
@override
State<PasswordValidationFormContent> createState() =>
_PasswordValidationFormContentState();
}
class _PasswordValidationFormContentState
extends State<PasswordValidationFormContent> {
final _passwordController = TextEditingController();
@override
Widget build(BuildContext context) {
return ListView(
padding: const EdgeInsets.all(16),
children: [
ValidatedPassword(_passwordController),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () {
if (Form.of(context)!.validate()) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text('Valid password: ${_passwordController.text}')),
);
}
},
child: const Text('Submit'),
),
],
);
}
}
class PasswordCheck {
const PasswordCheck(this.title, this.error, this.checker);
final String title;
final String error;
final bool Function(String password) checker;
}
class ValidatedPassword extends StatefulWidget {
const ValidatedPassword(this.passwordController, {super.key});
final TextEditingController passwordController;
@override
ValidatedPasswordState createState() => ValidatedPasswordState();
}
class ValidatedPasswordState extends State<ValidatedPassword> {
ValidatedPasswordState();
@override
void initState() {
super.initState();
widget.passwordController.addListener(setStateSafe);
}
void setStateSafe() {
if (mounted) {
setState(() {});
}
}
@override
void dispose() {
super.dispose();
widget.passwordController.removeListener(setStateSafe);
}
static List<PasswordCheck> checks = [
PasswordCheck(
'Includes a lowercase letter',
'Password must include a lowercase letter',
(password) => password.contains(RegExp(r'[a-z]')),
),
PasswordCheck(
'At least 8 characters',
'Password must be at least 8 characters',
(password) => password.length >= 8,
),
PasswordCheck(
'Includes a digit',
'Password must include a digit',
(password) => password.contains(RegExp(r'[0-9]')),
),
PasswordCheck(
'Includes a symbol',
'Password must include a symbol',
(password) => password.contains(RegExp(r'[!@#$%^&*(),.?":{}|<>]')),
),
PasswordCheck(
'Includes an uppercase letter',
'Password must include an uppercase letter',
(password) => password.contains(RegExp(r'[A-Z]')),
),
];
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.lock),
labelText: 'Password',
),
controller: widget.passwordController,
obscureText: true,
validator: (value) {
for (final check in checks) {
if (!check.checker(value!)) {
return check.error;
}
}
return null;
},
),
for (var check in checks)
if (check.checker(widget.passwordController.text))
ListTile(
leading: const Icon(Icons.check),
title: Text(check.title),
)
else
ListTile(
leading: const Icon(Icons.close),
title: Text(check.title),
),
TextFormField(
decoration: const InputDecoration(
icon: Icon(Icons.lock),
labelText: 'Confirm Password',
),
obscureText: true,
validator: (value) {
if (value != widget.passwordController.text) {
return 'Passwords do not match';
}
return null;
},
),
],
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment