Search code examples
flutterdartvalidation

Add validation to date TextFormField


I faced with the problem of validating text fields. Here you need to enter the date in the format dd.mm.yyyy. I also use flutter_multi_formatter package for this form.

import 'package:flutter/material.dart';
import 'package:flutter_multi_formatter/formatters/masked_input_formatter.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(home: StartPage());
  }
}

class StartPage extends StatelessWidget {
  const StartPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Padding(
        padding: const EdgeInsets.symmetric(vertical: 300, horizontal: 50),
        child: TextFormField(
          onChanged: (val) {},
          keyboardType: TextInputType.number,
          decoration: const InputDecoration(hintText: 'dd.mm.yyyy'),
          inputFormatters: [MaskedInputFormatter('##.##.####')],
        ),
      ),
    );
  }
}

For example, user will start entering an incorrect date format: 32.13.2009. And I want the text with the error notification to appear below this form. Is it possible to add validation for this form if an incorrect date is entered? Maybe it's good to parse the entered text and use conditions to compare numbers. I will be glad any help.


Solution

  • The DateTime.parse already does the date validation. So you can convert the date to string with the original format and then compare if its matching the input.

    Ravindra S. Patil ideia to use extension is great, so I only change the validation:

    extension DateValidator on String {
      bool isValidDate() {
        final dateArray = this.split(".");
    
        final day = dateArray[0];
        final month = dateArray[1];
        final year = dateArray[2];
    
        final date = DateTime.parse('$year$month$day');
    
        final originalFormatString = toOriginalFormatString(date);
        return this == originalFormatString;
      }
    
      String toOriginalFormatString(DateTime dateTime) {
        final day = dateTime.day.toString().padLeft(2, '0');
        final month = dateTime.month.toString().padLeft(2, '0');
        final year = dateTime.year.toString().padLeft(4, '0');
    
        return "$day.$month.$year";
      }
    }
    

    Example of use:

    void main() {
      print("37.15.2009".isValidDate()); // false
      print("37.12.2009".isValidDate()); // false
      print("31.15.2009".isValidDate()); // false
      print("30.11.2009".isValidDate()); // true
      print("25.12.2009".isValidDate()); // true
    }
    

    On the Widget:

    TextFormField(
      onChanged: (val) {},
      keyboardType: TextInputType.number,
      decoration: const InputDecoration(
        hintText: 'dd.mm.yyyy',
      ),
      inputFormatters: [MaskedInputFormatter('##.##.####')],
      validator: (value) {
        if (value == null || value.isEmpty) {
          return 'Please enter a date';
        } else if (!value.isValidDate()) {
          return 'Invalid date';
        }
    
        return null;
      },
    ),