Flutter’s Superpowers: Unleashing the Magic of Extensions and Typedefs for Form Validation & More

Stranger3145
5 min readApr 25, 2023

--

Hey there, fellow Flutter enthusiast! Are you tired of banging your head against the wall while dealing with repetitive form validation code? Wish you could sprinkle some magic dust on your Flutter apps to make them more efficient and maintainable?

Well, hold on to your hats, because I’ve got some exciting news for you! Flutter’s got a hidden gem in the form of extensions and typedefs that can turn your code into a spellbinding masterpiece. In this article, we’re diving headfirst into the enchanting world of Flutter’s extensions and typedefs, uncovering their mystical powers and showing you how they can transform your Flutter development game.

If you have been developing with Flutter for a while, you might have encountered extensions and typedefs. These two language features can make your code more concise, readable, and maintainable. This article will explore the benefits of using extensions and typedefs in Flutter.

So, grab your wand (or keyboard), and let’s cast some coding spells to unlock the true potential of your Flutter apps!

Extensions

Extensions are a powerful feature of Dart that allow you to add functionality to existing classes. With extensions, you can write methods, getters, and setters that appear to be part of the original class, even though they are not. For example, let’s say you want to add a method to the String class that capitalizes the first letter of each word in a string. You can do this with an extension. Here’s a sample code:

extension StringExtensions on String {
String capitalize() {
return this.split(' ').map((word) => word.substring(0, 1).toUpperCase() + word.substring(1)).join(' ');
}
}

With this extension, you can now call the capitalize method on any string:

String greeting = "hello world";
String capitalizedGreeting = greeting.capitalize();
print(capitalizedGreeting); // "Hello World"

Creating a Custom Color Palette With Extensions

In Flutter, you can define a custom color palette using MaterialColor class. However, it can be cumbersome to create a Map of shades for each color. To simplify this process, you can create an extension on theColor class to generate a MaterialColor. Here’s an example code to do this:

extension CustomColorPalette on Color {
MaterialColor createMaterialColor() {
final List<double> strengths = <double>[.05, .1, .2, .3, .4, .5, .6, .7, .8, .9];
Map<int, Color> swatch = {};
final int primaryValue = this.value;
for (int i = 0; i < 10; i++) {
final double strength = strengths[i];
final int alpha = (0xFF * strength).round();
final int value = (primaryValue & 0xFFFFFF) | (alpha << 24);
swatch[100 + i * 100] = Color(value);
}
return MaterialColor(primaryValue, swatch);
}
}

Now you can create a MaterialColor using any color:

Color myColor = Colors.blue;
MaterialColor myCustomColorPalette = myColor.createMaterialColor();

Validating Email Address Using Extensions

You may need to validate email addresses in your app. You can write an extension on String class to perform this validation:

extension EmailValidator on String {
bool isValidEmail() {
final RegExp emailRegex = RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$');
return emailRegex.hasMatch(this);
}
}

Now you can validate an email address easily:

String email = "test@example.com";
bool isValid = email.isValidEmail(); // true

Now that we’ve got an idea of how extensions work, let's take a look at TypeDefs and how they can make your life better;

Typedefs

Typedefs are another language feature of Dart that allow you to define function signatures. With typedefs, you can define a type alias for a function signature, which makes it easier to declare variables and parameters of that type. For example, let’s say you have a function that takes a String argument and returns an int:

int stringToInt(String str) {
return int.parse(str);
}

You can define a typedef for this function signature like this:

typedef StringToInt = int Function(String);

Now, you can declare a variable or parameter of the StringToInt type, which is equivalent to the function signature:

StringToInt myFunction = stringToInt;
int result = myFunction("123");

OnPressed Callback Using TypeDefs

In Flutter, you can pass a callback function to a RaisedButton's onPressed parameter. You can define a typedef for this callback to make your code more readable:

typedef OnPressedCallback = void Function();

class MyButton extends StatelessWidget {
final OnPressedCallback onPressed;
MyButton({required this.onPressed});

@override
Widget build(BuildContext context) {
return RaisedButton(
onPressed: onPressed,
child: Text("Press me!"),
);
}
}

Now you can use OnPressedCallback type instead of repeating the function signature throughout your code:

void _onButtonPressed() {
// do something
}

MyButton(
onPressed: _onButtonPressed,
)

Custom Validator Function using TypeDefs

In Flutter, you can use form validation to ensure that user input is valid. You can define a typedef for the validation function to make it easier to declare validator functions:

typedef ValidatorFunction<T> = String? Function(T);

class MyForm extends StatefulWidget {
@override
_MyFormState createState() => _MyFormState();
}

class _MyFormState extends State<MyForm> {
final _formKey = GlobalKey<FormState>();
String? _name;
String? _email;

String? _nameValidator(String? value) {
if (value == null || value.isEmpty) {
return "Please enter your name.";
}
return null;
}

String? _emailValidator(String? value) {
if (value == null || value.isEmpty) {
return "Please enter your email.";
}
if (!value.isValidEmail()) {
return "Please enter a valid email.";
}
return null;
}

@override
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
TextFormField(
decoration: InputDecoration(labelText: "Name"),
validator: _nameValidator,
onSaved: (value) => _name = value,
),
TextFormField(
decoration: InputDecoration(labelText: "Email"),
validator: _emailValidator,
onSaved: (value) => _email = value,
),
RaisedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
_formKey.currentState!.save();
// submit form data
}
},
child: Text("Submit"),
),
],
),
);
}
}

With the ValidatorFunction typedef, you can easily define validation functions with the same signature and reuse them throughout your code. This helps to keep your code DRY (Don't Repeat Yourself) and makes it easier to change the validation logic in the future.

Typedefs are particularly useful when you have complex function signatures that are used in multiple places in your code. By defining a typedef, you can give the function signature a name, which makes your code more readable and easier to understand.

Now that you’ve mastered the art of Flutter’s extensions and typedefs, you’re equipped with some truly magical powers! With the ability to streamline form validation, reduce code repetition, and wield the power of reusability, your Flutter apps are sure to soar to new heights of efficiency and maintainability.

So go forth, fellow developer, and wield the mighty sword of extensions and typedefs in your Flutter adventures. Let your code shine with the brilliance of your newfound skills, and watch your apps become legendary in the Flutterverse. Happy coding, and may the extensions and typedefs be ever in your favor! 🚀✨🔥

--

--