Home > Net >  how to call a Function from another Dart file
how to call a Function from another Dart file

Time:02-06

i have this funtion which handles my Date and Time picker widget ...Code bellow...

Future selectDayAndTimeL(BuildContext context) async {
    DateTime? selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget? child) => child!);

    TimeOfDay? selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (selectedDay != null && selectedTime != null) {
      //a little check
    }
    setState(() {
      selectedDateAndTime = DateTime(
        selectedDay!.year,
        selectedDay!.month,
        selectedDay!.day,
        selectedTime!.hour,
        selectedTime!.minute,
      );
      // _selectedDate = _selectedDay;
    });
    // print('...');
  }

initially it was inside my add new task class/dart file "Stateful Widget", and everything was working fine but now i want to also use that function on the Home screen when a button is pressed.

Then i checked a StackOverflow question on enter image description here Bellow s the error i got when i tried to call

onPressed: () => selectedDateAndTime!.selectDayAndTimeL(),

enter image description here

what should i do from here?

CodePudding user response:

I'm guessing that you originally had a Statefull widget, that probably looked something like this:

class OriginalWidget extends StatefulWidget {
  @override
  _OriginalWidgetState createState() => _OriginalWidgetState();
}

class _OriginalWidgetState extends State<OriginalWidget> {

  DateTime? _selectedDate;
  DateTime? selectedDateAndTime;

  Future selectDayAndTimeL(BuildContext context) async {
    DateTime? selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget? child) => child!);

    TimeOfDay? selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (selectedDay != null && selectedTime != null) {
      //a little check
    }
    setState(() {
      selectedDateAndTime = DateTime(
        selectedDay!.year,
        selectedDay!.month,
        selectedDay!.day,
        selectedTime!.hour,
        selectedTime!.minute,
      );
      // _selectedDate = _selectedDay;
    });
    // print('...');
  }

  @override
  Widget build(BuildContext context) {
    return FlatButton(
          onPressed: () => selectDayAndTimeL(context));
  } 
} 

Now, what you want to do is to reuse the logic of your selectDayAndTimeL function.

The problem is that both the selectedDateAndTime variable and the setState method are specific to the Statefull widget _OriginalWidgetState.

What you need to do is to modify your selectDayAndTimeL function so that it can take those widget-specific stuff as parameters.

Si, in essence what you would do is:

1st create the function as a standalone function, for instance in a new dart file. Make sure to remove the widget-specific stuff from the body and leave them as parameters:

  Future selectDayAndTimeL(BuildContext context, void Function(DateTime) onDateAndTimeSelected) async {
    DateTime? selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget? child) => child!);

    TimeOfDay? selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (selectedDay != null && selectedTime != null) {
      //a little check
    }
    
      onDateAndTimeSelected(DateTime(
        selectedDay!.year,
        selectedDay!.month,
        selectedDay!.day,
        selectedTime!.hour,
        selectedTime!.minute,
      ));
    // print('...');
  }

2nd, on your new Statefull widgets, you may now call this function, make sure that you send the new onDateAndTimeSelected parameter:

class SecondWidget extends StatefulWidget {
  @override
  _SecondWidgetState createState() => _SecondWidgetState();
}

class _SecondWidgetState extends State<SecondWidget> {
  DateTime? selectedDateAndTime;

  @override
  Widget build(BuildContext context) {
    return FlatButton(
          onPressed: () => selectDayAndTimeL(context, 
        setState((DateTime selectedValue) {
             selectedDateAndTime = selectedValue;
         } ) 
    ));
  }  
} 

And then you could just follow the same logic for any other Statefull widget that needs to call your function.

CodePudding user response:

setState tells a stateful widget to re-render based on the changed data. In your case you are changing selectedDateAndTime and re-building the Widget with updated data.

If you want to update/rebuild a widget from a "remote" function you need to use a callback.

Future selectDayAndTimeL(BuildContext context,Function(DateTime time) onDateTimeSelected)  async {
    DateTime? selectedDay = await showDatePicker(
        context: context,
        initialDate: DateTime.now(),
        firstDate: DateTime(2021),
        lastDate: DateTime(2030),
        builder: (BuildContext context, Widget? child) => child!);

    TimeOfDay? selectedTime = await showTimePicker(
      context: context,
      initialTime: TimeOfDay.now(),
    );

    if (selectedDay != null && selectedTime != null) {
      //a little check
    }
    // call the callback here with your calculated data
    onDateTimeSelected(
      DateTime(
        selectedDay!.year,
        selectedDay!.month,
        selectedDay!.day,
        selectedTime!.hour,
        selectedTime!.minute,
      ),
    );
  }

Then in the StatefulWidget where you call this function:

selectDayAndTimeL(BuildContext context,(time) {
  setState(() {
    selectedDateAndTime = time;
  });
});
  •  Tags:  
  • Related