Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to disable list of specific date on flutter

I have a code to call showDatePicker, my question is how to disable list of specific date, one, two or more json dates? I try selectableDayPredicate with Saturday and Sunday disabled, but how to do disable with json list of date from api ?

                onTap: () {
                            showDatePicker(
                              context: context,
                              initialDate:
                                  DateTime.now().add(Duration(days: 2)),
                              firstDate:
                                  DateTime.now().add(Duration(days: 1)),
                              lastDate:
                                  DateTime.now().add(Duration(days: 730)),
                              selectableDayPredicate: (DateTime val) =>
                                  val.weekday == 5 || val.weekday == 6
                                      ? false
                                      : true,
                            );
                          }
like image 445
RIFAL Avatar asked Dec 13 '22 13:12

RIFAL


1 Answers

This depends a lot on the data you're getting from your API. That I can't help you with, but the predicate I can.

Assuming you've retrieved a json list from your server that contains a bunch of strings, parsed them into DateTime objects (probably using something like DateTime.parse), then it's relatively simple.

Basically, you need to check for each date (using the selectableDayPredicate) and return true if it is not in your list.

First, you'll need to sanitize the DateTime objects as they may contain hours, seconds, milliseconds etc. And you need to make them into a format that can be searched quickly - so probably not DateTime. DateTimes would technically work as they do have a hashCode implementation, but you'd have to create new DateTime objects that only include year, month and day anyways (as a datetime with +1 millisecond is technically a different value than one without it). If you really wanted to do it that way you could change the sanitizeDateTime function below to return a DateTime and getDateSet to return a Set<DateTime>, but what I'd recommend is making them into Strings as they work well in sets and are simple.

So you'll need a function something like:

String sanitizeDateTime(DateTime dateTime) => "${dateTime.year}-${dateTime.month}-${dateTime.day}";

And wherever you get your json you'll want to format it using that and insert it into a set.

Set<String> getDateSet(List<DateTime> dates) => dates.map(sanitizeDateTime).toSet();

It's important that you have a Set of strings rather than a List as selectableDayPredicate will run a bunch of times, and if you were iterating through an entire list of unselectable dates each time you did that (which is what List's contains does), it could get slow as it's O(n*m) where n is the number of dates being checked and m is the number of unselectable dates - whereas if you use a set, contains uses a more efficient hash computation and then lookup which results in O(n). This could be construed as premature optimization, but in this case I think it's a worthwhile one.

Once you have the set of unselectable dates, you simply have to check against them in the predicate.

i.e.

class .... {
  Set<String> unselectableDates; // assuming this is set somewhere

  ....
    onTap: () {
      showDatePicker(
        ...
        selectableDayPredicate: (DateTime val) {
          String sanitized = sanitizeDateTime(val);
          return !unselectableDates.contains(sanitized);
        }
    }
}
like image 51
rmtmckenzie Avatar answered Jan 29 '23 01:01

rmtmckenzie