Home > database >  Navigating to another page in Flutter with and without arguments
Navigating to another page in Flutter with and without arguments

Time:02-28

I've only been coding in Flutter for a few weeks now and I would like to know if it is possible just to navigate to a page using named routes that has received arguments from another page? The main objective is to navigate to the Cart Screen from two different pages where one passes an argument while the other doesn't. Here is my code below to explain my question:

This is the first part of the code which navigates to the cart screen after passing arguments id and quantity

class ItemDetailsState extends State<ItemDetails> {
  int quantity = 1;       //quantity

  @override
  Widget build(BuildContext context) {
   final routes =
        ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;
    final id = routes["id"];     //id
return Scaffold(
......
InkWell(
                onTap: () {
                  Navigator.of(context).pushNamed('/cart-screen', arguments: {  //This navigates to the cart screen passing arguments id and quantity
                    'id': routes["id"],
                    'quantity': quantity,
                  });
                  Provider.of<CartItemProvider>(context, listen: false)
                      .addItems(id, name, restaurantName, price, quantity);
                },
);
}
}

This is the Cart Screen that receives the arguments and filters data from a Provider Class:

class CartScreen extends State<CartScreenState> {
  @override
  Widget build(BuildContext context) {
    final routes =
        ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;   
    final id = routes['id'];             //Received Arguments
    final quantity = routes['quantity']; //Received Arguments
    final provider =
        Provider.of<PopularDishesProvider>(context).getProductById(id);    //Provider that filters the data as per ID

My idea is to navigate to the Cart Screen page from another page like this but it throws the below error:

class HomeScreenState extends State<HomeScreen> {
Widget build(BuildContext context) {
return Scaffold(
..............
body: Row(
                          children: [
                            InkWell(
                              onTap: () => Navigator.of(context)
                                  .pushReplacementNamed('/cart-screen'),      //Navigate to the Cart Screen
                              child: const Icon(
                                Icons.shopping_cart_outlined,
                                color: Colors.grey,
                                size: 30,
                              ),
                            ),
                            InkWell(
                              onTap: () {},
                              child: const Icon(
                                Icons.notifications_none_outlined,
                                color: Colors.grey,
                                size: 30,
                              ),
                            )
                          ],
                        )

The method '[]' was called on null.
Receiver: null
Tried calling: []("id")

The above error I believe is owing to the fact that I'm trying to just navigate to '/cart-screen' without passing any argument in the HomeScreenState widget. I need suggestions to know if there's any way to get around this?

The route is declared in the main.dart file as it should like

routes : {
'/cart-screen': (context) => CartScreen(),
}

CodePudding user response:

You can check null value using

 @override
  Widget build(BuildContext context) {
 var arguments3 = ModalRoute.of(context)!.settings.arguments;

var routes=
    arguments3!=null? arguments3 as  Map<String, dynamic>:{}; 
    final id = routes['id']??0;             //Received Arguments
    final quantity = routes['quantity']??0; //Received Arguments
    final provider =
        Provider.of<PopularDishesProvider>(context).getProductById(id);

We can pass argument with the help of argument property in pushnamed method

 Navigator.pushNamed(context, AppRoutes.Page1,
                arguments: {"name": "lava", "body": "chi"});

Receive value

  var arguments3 = ModalRoute.of(context)!.settings.arguments;

    var arguments2 =
        arguments3!=null? arguments3 as  Map<String, dynamic>:{};

May like this

enter image description here

SAmple Code

import 'package:flutter/material.dart';

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

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

  static const String _title = 'Flutter Code Sample';

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: "/",
      routes: {
        AppRoutes.home: (context) => Home(),
        AppRoutes.Page1: (context) => Page1(),
      },
      title: _title,
      // home: ,
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("title")),
      body: const Center(
        child: MyStatelessWidget(),
      ),
    );
  }
}

var _color = Colors.black;
var _value = 0.0;

class MyStatelessWidget extends StatefulWidget {
  const MyStatelessWidget({Key? key}) : super(key: key);

  @override
  State<MyStatelessWidget> createState() => _MyStatelessWidgetState();
}

class _MyStatelessWidgetState extends State<MyStatelessWidget> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, AppRoutes.Page1);
              },
              child: Text("Without Argument")),
          ElevatedButton(
              onPressed: () {
                Navigator.pushNamed(context, AppRoutes.Page1,
                    arguments: {"name": "lava", "body": "chi"});
              },
              child: Text("With Argument")),
        ],
      ),
    );
  }

  @override
  void initState() {}
}

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

  @override
  Widget build(BuildContext context) {

    var arguments3 = ModalRoute.of(context)!.settings.arguments;

    var arguments2 =
        arguments3!=null? arguments3 as  Map<String, dynamic>:{};
            // {"name": "nodata", "body": "no data"};
    return Material(
      child: Center(
        child: Container(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              Text(arguments2["name"] ?? "Nodata",
                  style: TextStyle(fontSize: 30)),
              Text(
                arguments2["body"] ?? "No DAta",
                style: TextStyle(fontSize: 30),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class AppRoutes {
  static String failed = "/page2";
  static String Page1 = "/page1";
  static String home = "/";
}

CodePudding user response:

your design is a little confusing. if you are trying to get the ID and Quantity in the Cart-screen, then why do you want to navigate to it without the arguments?

any how, I guess you have a use case where you want to do different thing if the arguments are not passed. then the only thing you need is to check if the arguments are null. right?

  @override
  Widget build(BuildContext context) {
    final routes =
        ModalRoute.of(context)!.settings.arguments as Map<String, dynamic>;   
    if (routes != null) {
        final id = routes['id'];             //Received Arguments
        final quantity = routes['quantity']; //Received Arguments
        final provider =
            Provider.of<PopularDishesProvider>(context).getProductById(id); 
    } else {
        // do the things here when no argument is passed.
    }
  • Related