Flutter | How to validate time picker

Viewed 2117

Here I want to validate the time picker. when I am going to select the time from the time picker it must only allow me to select the current time or before the current time. I am not supposed to allow select future time.

Here is the time picker snippet I've tried.

DateTimeField(
      format: format,
      autocorrect: true,
      autovalidate: false,
      controller: _serviceDate,
      readOnly: true,
      validator: (date) => (date == null || _serviceDate.text == '')
          ? 'Please enter valid date'
          : null,
      onShowPicker: (context, currentValue) async {
        final date = await showDatePicker(
            context: context,
            firstDate: DateTime.now(),
            initialDate: currentValue ?? DateTime.now(),
            lastDate: DateTime(2100));
        if (date != null) {
          final time = await showTimePicker(
            context: context,
            initialTime: TimeOfDay.fromDateTime(
              currentValue ?? DateTime.now(),
            ),
          );
          return DateTimeField.combine(date, time);
        } else {
          return currentValue;
        }
      },
    );
1 Answers

You can enable autovalidateMode on DateTimeField then check the DateTime difference of the selected DateTime with the current DateTime. If the time difference is negative, this means the selected DateTime is in the past.

DateTimeField(
  format: format,
  autocorrect: true,
  readOnly: true,
  autovalidateMode: AutovalidateMode.onUserInteraction,
  validator: (DateTime? selectedDateTime) {
    if (selectedDateTime != null) {
      // If the DateTime difference is negative,
      // this indicates that the selected DateTime is in the past
      if (selectedDateTime.difference(DateTime.now()).isNegative) {
        debugPrint('Selected DateTime is in the past');
      } else {
        debugPrint('Selected DateTime is in the future');
      }
    }
  },
  onShowPicker: ...
),

Aside from that, you might also want to consider setting the lastDate on showDatePicker to DateTime.now() so future dates can't be selected.

Here's the complete sample that you can try out.

import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';

void main() {
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final format = DateFormat("yyyy-MM-dd HH:mm");

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            DateTimeField(
              format: format,
              autocorrect: true,
              readOnly: true,
              autovalidateMode: AutovalidateMode.onUserInteraction,
              validator: (DateTime? selectedDateTime) {
                if (selectedDateTime != null) {
                  // If the DateTime difference is negative,
                  // this indicates that the selected DateTime is in the past
                  if (selectedDateTime.difference(DateTime.now()).isNegative) {
                    debugPrint('Selected DateTime is in the past');
                  } else {
                    debugPrint('Selected DateTime is in the future');
                  }
                }
              },
              onShowPicker: (context, currentValue) async {
                final date = await showDatePicker(
                    context: context,
                    firstDate: DateTime(1900),
                    initialDate: DateTime.now(),
                    lastDate: DateTime.now());
                if (date != null) {
                  final time = await showTimePicker(
                    context: context,
                    initialTime: TimeOfDay.fromDateTime(
                      currentValue ?? DateTime.now(),
                    ),
                  );
                  return DateTimeField.combine(date, time);
                } else {
                  return currentValue;
                }
              },
            ),
          ],
        ),
      ),
    );
  }
}
Related