How to check for a nullable value in DateTime initialized variable in Flutter

Viewed 5339

There are two main issues :

  1. The initialization of DateTime variable is not allowed
  2. The ternary check for a dateTime variable once randomly initialized by Date.now() still cant check for null value.

The error in DateTime variable assigning

After initialization of DateTime variable with Date.now()

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

class NewTransaction extends StatefulWidget {
  final Function transactionAddHandler;

  NewTransaction(this.transactionAddHandler);

  @override
  _NewTransactionState createState() => _NewTransactionState();
}

class _NewTransactionState extends State<NewTransaction> {
  final _titleController = TextEditingController();
  final _amountController = TextEditingController();
  DateTime _selectedDate;

  void _submitData() {
    final enteredTitle = _titleController.text;
    final enteredAmount = double.parse(_amountController.text);
    if (enteredAmount <= 0 || enteredTitle.isEmpty) {
      return;
    }
    widget.transactionAddHandler(enteredTitle, enteredAmount);

    Navigator.of(context).pop();
  }

  void _presentDatePicker() {
    showDatePicker(
      context: context,
      initialDate: DateTime.now(),
      firstDate: DateTime(2021),
      lastDate: DateTime.now(),
    ).then((pickedDate) {
      if (pickedDate == null) {
        return;
      }

      setState(() {
        _selectedDate = pickedDate;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 5,
      child: Padding(
        padding: EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Title'),
              controller: _titleController,
              onSubmitted: (_) => _submitData(),
            ),
            TextField(
              decoration: InputDecoration(labelText: 'Amount'),
              keyboardType: TextInputType.number,
              controller: _amountController,
              onSubmitted: (_) => _submitData(),
            ),
            Container(
              height: 70,
              child: Row(
                children: <Widget>[
                  Text(
                    _selectedDate == null
                        ? 'No Date Chosen!'
                        : DateFormat.yMd().format(_selectedDate),
                  ),
                  FlatButton(
                    textColor: Theme.of(context).primaryColor,
                    child: Text(
                      'Choose Date',
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    onPressed: _presentDatePicker,
                  )
                ],
              ),
            ),
            RaisedButton(
              onPressed: _submitData,
              child: Text(
                'Add Transaction',
              ),
              textColor: Colors.white,
              color: Theme.of(context).primaryColor,
            )
          ],
        ),
      ),
    );
  }
}

Do help me and the flutter community grow better. Thank you in advance.

6 Answers

If _selectedDate property does not have a default value, make it nullable:

class _NewTransactionState extends State<NewTransaction> {
  ...
  DateTime? _selectedDate;

  ...
}

The _selectedDate is nullable. So mark the variable as,

DateTime? _selectedDate;

And before using it have to check for null first,

Text(_selectedDate == null
     ? 'No Date Chosen!'
     : DateFormat.yMd().format(_selectedDate!),
    ),

Helpful Links->

  1. Null safety
  2. Promotion Failure
  1. Declare the variable like: DateTime? _selectedDate;
  2. If you get the error The argument type 'DateTime?' can't be assigned to the parameter type 'DateTime' then assign like:
Text(
    _selectedDate == null
        ? 'No Date Chosen!'
        : DateFormat.yMd().format(_selectedDate ?? DateTime.now()),
),

You can use a boolean variable to check if isDateSelected or not:

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

class NewTransaction extends StatefulWidget {
  final Function transactionAddHandler;

  NewTransaction(this.transactionAddHandler);

  @override
  _NewTransactionState createState() => _NewTransactionState();
}

class _NewTransactionState extends State<NewTransaction> {
  final _titleController = TextEditingController();
  final _amountController = TextEditingController();
  late DateTime _selectedDate;
  bool _isDateSelected = false;

  void _submitData() {
    final enteredTitle = _titleController.text;
    final enteredAmount = double.parse(_amountController.text);
    if (enteredAmount <= 0 || enteredTitle.isEmpty) {
      return;
    }
    widget.transactionAddHandler(enteredTitle, enteredAmount);

    Navigator.of(context).pop();
  }

  void _presentDatePicker() {
    showDatePicker(
      context: context,
      initialDate: DateTime.now(),
      firstDate: DateTime(2021),
      lastDate: DateTime.now(),
    ).then((pickedDate) {
      if (pickedDate == null) {
        return;
      }

      setState(() {
        _isDateSelected = true;
        _selectedDate = pickedDate;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 5,
      child: Padding(
        padding: EdgeInsets.all(10),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.end,
          children: <Widget>[
            TextField(
              decoration: InputDecoration(labelText: 'Title'),
              controller: _titleController,
              onSubmitted: (_) => _submitData(),
            ),
            TextField(
              decoration: InputDecoration(labelText: 'Amount'),
              keyboardType: TextInputType.number,
              controller: _amountController,
              onSubmitted: (_) => _submitData(),
            ),
            Container(
              height: 70,
              child: Row(
                children: <Widget>[
                  Text(
                    !_isDateSelected
                        ? 'No Date Chosen!'
                        : DateFormat.yMd().format(_selectedDate),
                  ),
                  FlatButton(
                    textColor: Theme.of(context).primaryColor,
                    child: Text(
                      'Choose Date',
                      style: TextStyle(
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    onPressed: _presentDatePicker,
                  )
                ],
              ),
            ),
            RaisedButton(
              onPressed: _submitData,
              child: Text(
                'Add Transaction',
              ),
              textColor: Colors.white,
              color: Theme.of(context).primaryColor,
            )
          ],
        ),
      ),
    );
  }
}

Change DateTime _selectedaDate; to String _ selectedate="";

Where _selectedDate = pickedDate; change to _selectedDate = pickedDate.toString();

Any time u need _selectedDate in DateTime use this: DateTime.parse(_selectedDate).

If _selectedDate property does not have a default value, make it nullable

late DateTime? _selectedDate = null;

and then you can use like this

 `Text(_selectedDate == null
     ? "Date is not selected yet      "
     : DateFormat.yMd().format(_selectedDate!))`,
Related