skip to Main Content

Let’s say the ManageBookingPage widget requires an object called trip as an argument. But this widget has the ability to modify the received argument such that it becomes null (trip = null).

I want this widget to pop out of the tree automatically when trip becomes null. What would be the best approach in achieving this?

class ManageBookingPage extends StatefulWidget {
  const ManageBookingPage({
    super.key,
    required this.trip,
  });

  final BusTrip trip;

  @override
  State<ManageBookingPage> createState() => _ManageBookingPageState();
}

class _ManageBookingPageState extends State<ManageBookingPage> {
  @override
  Widget build(BuildContext context) {
    return SizedBox(
      child: Text(widget.trip.date.toString()),
    );
}

3

Answers


  1. You can use the ternary operator to achieve it.

    import 'package:flutter/material.dart';
    
    class ManageBookingPage extends StatefulWidget {
      const ManageBookingPage({
        super.key,
        required this.trip,
      });
    
      final BusTrip? trip;
    
      @override
      State<ManageBookingPage> createState() => _ManageBookingPageState();
    }
    
    class _ManageBookingPageState extends State<ManageBookingPage> {
      @override
      Widget build(BuildContext context) {
        return widget.trip != null ? SizedBox(
            child: Text(widget.trip.date.toString()),
          ) : const SizedBox.shrink();
      }
    }
    

    In this case if trip is not null it will render the widget :

    SizedBox(
       child: Text(widget.trip.date.toString()),
    )
    

    And if the trip is null it will display SizedBox.shrink(), and the previous widget won’t be rendered, removing it out of the tree.

    Login or Signup to reply.
  2. To automatically remove the ManageBookingPage widget from the navigation stack when the trip becomes null, you can use a ValueNotifier and listen for changes to trip. When trip becomes null, you can use Navigator.pop() to remove the widget from the stack.

    Example code:

    import 'package:flutter/material.dart';
    
    class ManageBookingPage extends StatefulWidget {
      const ManageBookingPage({
        super.key,
        required this.tripNotifier,
      });
    
      final ValueNotifier<BusTrip?> tripNotifier;
    
      @override
      State<ManageBookingPage> createState() => _ManageBookingPageState();
    }
    
    class _ManageBookingPageState extends State<ManageBookingPage> {
      @override
      void initState() {
        super.initState();
        // Add a listener to the ValueNotifier
        widget.tripNotifier.addListener(_checkTrip);
      }
    
      void _checkTrip() {
        // Check if the trip is null
        if (widget.tripNotifier.value == null) {
          Navigator.of(context).pop(); // Remove the widget from the navigation stack
        }
      }
    
      @override
      void dispose() {
        // Remove the listener when the widget is disposed
        widget.tripNotifier.removeListener(_checkTrip);
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return SizedBox(
          child: Text(widget.tripNotifier.value?.date.toString() ?? 'No trip'),
        );
      }
    }
    
    class BusTrip {
      final DateTime date;
      BusTrip(this.date);
    }
    

    Explanation

    1. ValueNotifier<BusTrip?> tripNotifier: A ValueNotifier is used to observe changes in trip.

    2. addListener(_checkTrip): Adds a listener to tripNotifier that triggers _checkTrip whenever trip changes.

    3. _checkTrip: Checks if trip is null. If so, it calls Navigator.of(context).pop() to remove the widget from the navigation stack.

    4. dispose(): Removes the listener when the widget is disposed to prevent memory leaks.

    Login or Signup to reply.
  3. I tried to add trip management in this page and add a listener when the trip value has been change to null the page will be poped.

    class ManageBookingPage extends StatefulWidget {
      const ManageBookingPage({
        super.key,
        required this.trip,
      });
    
      final BusTrip trip;
    
      @override
      State<ManageBookingPage> createState() => _ManageBookingPageState();
    }
    
    class _ManageBookingPageState extends State<ManageBookingPage> {
      // Define new trip variable for this page for managing trip value state
      late final ValueNotifier<BusTrip?> trip;
    
      @override
      void initState() {
        super.initState();
    
        // Assign trip for this page from previous page (parameter argument)
        trip = ValueNotifier<BusTrip?>(widget.trip);
    
        // Add [trip] listener to notify when trip value has been changed
        //
        // The function inside listener will be executed when the [trip.value] changed.
        trip.addListener(() {
          if (trip.value == null) Navigator.pop(context);
        });
      }
    
      @override
      void dispose() {
        trip.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Center(
          child: Column(
            children: [
              Text(widget.trip.date.toString()),
    
              // Add distance for other widget
              const SizedBox(height: 16),
    
              // A button for remove trip value
              ElevatedButton(
                onPressed: () {
                  // Remove trip value by assign it to null
                  trip.value = null;
                },
                child: const Text('Remove Trip'),
              ),
            ],
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search