Search code examples
flutterdartdrop-down-menuargumentsinstance

Flutter - How to include other values in dropdown and other flutter features?


Hi i'm trying to figure this out for so long and still not sure how to pass the values in dropdown...

Provider-Category:

import 'package:flutter/foundation.dart';
class Category with ChangeNotifier {
  final String id;
  final String title;
  Category({
    @required this.id,
    @required this.title,
  });
}

Provider-Categories:

import 'package:flutter/material.dart';
import './category.dart';
class Categories with ChangeNotifier {
  List < Category > _items = [
    Category(
      id: 'id1',
      title: 'Default',
    ),
    Category(
      id: 'id2',
      title: 'French Lesson',
    ),
    Category(
      id: 'id3',
      title: 'Spanish Lesson',
    ),
  ];
}

Screen:

1.I need the Default option selected initially if there is no other categories else choose the last on the list

2.If drop-down selected option is changed and Icon list is pressed it should pass the selected values (id and title)

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../providers/categories.dart';
...
void getDropDownItem(BuildContext ctx) {
  setState(() {
    Navigator.of(ctx).pushNamed(
      CategoryNotesScreen.routeName,
      arguments: { //on this part, i'm not sure how will I get the values of selected option in dropdown (ID and title) onpress of icon?
        'id': catId,
        'title': catTitle
      }
    );
  });
}
@override
Widget build(BuildContext context) {
  ...
  final categoriesData = Provider.of < Categories > (context);
  final categoriesDataItems = categoriesData.items;
  ...
  appBar: AppBar(
    title: const Text("New Note"),
      actions: < Widget > [
        IconButton(
          icon: const Icon(
              Icons.list),
            onPressed: () => getDropDownItem(context),
        ),
      ],
  ),
  ...
  child: DropdownButtonFormField(
    items: categoriesDataItems.map((categoriesDataItemsMap) => DropdownMenuItem(
      child: Text(categoriesDataItemsMap.title),
      value: categoriesDataItemsMap.id,
    ), ).toList(),
    value: selectedCatId,
    onChanged: (newValue) {
      setState(() {
        print(newValue);
        selectedCatId = newValue;
      });
    },
  ),
}

New screen: I need to get the selected category arguments to display the Category Title and be able to use the Category ID in filtering from the list.

import 'package:flutter/material.dart';
class CategoryNotesScreen extends StatelessWidget {
  static
  const routeName = '/category-notes';
  @override
  Widget build(BuildContext context) {
    final routeArgs =
      ModalRoute.of(context).settings.arguments as Map < String, String > ;
    print('cat_notes_screen');
    print(routeArgs);
    final catId = routeArgs['id'];
    final catTitle = routeArgs['title'];
    return Scaffold(
      appBar: AppBar(
        title: Text('catTitle'),
      ),
      body: Center(
        child: Text(
          'The Recipes For The Category!',
        ),
      ),
    );
  }
}

Sorry I'm very new to flutter and still learning...


Solution

  • You can copy paste run full code below
    You can see working demo below
    Step 1: CategoryNotesScreen get arguments

    Category routeArgs = ModalRoute.of(context).settings.arguments;
    

    Step 2: getDropDownItem pass selectedCategory

    Category selectedCategory;
    
    void getDropDownItem(BuildContext ctx) {
        setState(() {
          Navigator.of(ctx).pushNamed(CategoryNotesScreen.routeName,
              arguments: selectedCategory);
        });
      }
    

    Step 3: Set default selectedCategory, you can use categoriesDataItems.first or last

      @override
      void initState() {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          final categoriesData = Provider.of<Categories>(context, listen: false);
          final categoriesDataItems = categoriesData.items;
          setState(() {
            selectedCategory = categoriesDataItems.first;
          });
        });
        super.initState();
      }
    

    Step 4: Use DropdownButtonFormField<Category>

    DropdownButtonFormField<Category>(
          items: categoriesDataItems
              .map(
                (categoriesDataItemsMap) => DropdownMenuItem(
                  child: Text(categoriesDataItemsMap.title),
                  value: categoriesDataItemsMap,
                ),
              )
              .toList(),
          value: selectedCategory,
          onChanged: (newValue) {
            setState(() {
              print(newValue);
              selectedCategory = newValue;
            });
          },
        ),
    

    working demo

    enter image description here

    full code

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    
    class Category {
      final String id;
      final String title;
      Category({
        @required this.id,
        @required this.title,
      });
    }
    
    class Categories with ChangeNotifier {
      List<Category> items = [
        Category(
          id: 'id1',
          title: 'Default',
        ),
        Category(
          id: 'id2',
          title: 'French Lesson',
        ),
        Category(
          id: 'id3',
          title: 'Spanish Lesson',
        ),
      ];
    }
    
    void main() {
      runApp(
        ChangeNotifierProvider(
          create: (context) => Categories(),
          child: MyApp(),
        ),
      );
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          initialRoute: '/',
          routes: {
            '/': (context) => MyHomePage(
                  title: "test",
                ),
            '/category-notes': (context) => CategoryNotesScreen(),
          },
        );
      }
    }
    
    class CategoryNotesScreen extends StatelessWidget {
      static const routeName = '/category-notes';
    
      @override
      Widget build(BuildContext context) {
        Category routeArgs = ModalRoute.of(context).settings.arguments;
        print('cat_notes_screen');
        print(routeArgs);
        final catId = routeArgs.id;
        final catTitle = routeArgs.title;
        return Scaffold(
          appBar: AppBar(
            title: Text('catTitle $catTitle'),
          ),
          body: Center(
            child: Text(
              '$catId $catTitle The Recipes For The Category!',
            ),
          ),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);
    
      final String title;
    
      @override
      _MyHomePageState createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      Category selectedCategory;
    
      void getDropDownItem(BuildContext ctx) {
        setState(() {
          Navigator.of(ctx).pushNamed(CategoryNotesScreen.routeName,
              arguments: selectedCategory);
        });
      }
    
      @override
      void initState() {
        WidgetsBinding.instance.addPostFrameCallback((_) {
          final categoriesData = Provider.of<Categories>(context, listen: false);
          final categoriesDataItems = categoriesData.items;
          setState(() {
            selectedCategory = categoriesDataItems.first;
          });
        });
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        final categoriesData = Provider.of<Categories>(context);
        final categoriesDataItems = categoriesData.items;
    
        return Scaffold(
          appBar: AppBar(
            title: const Text("New Note"),
            actions: <Widget>[
              IconButton(
                icon: const Icon(Icons.list),
                onPressed: () => getDropDownItem(context),
              ),
            ],
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                DropdownButtonFormField<Category>(
                  items: categoriesDataItems
                      .map(
                        (categoriesDataItemsMap) => DropdownMenuItem(
                          child: Text(categoriesDataItemsMap.title),
                          value: categoriesDataItemsMap,
                        ),
                      )
                      .toList(),
                  value: selectedCategory,
                  onChanged: (newValue) {
                    setState(() {
                      print(newValue);
                      selectedCategory = newValue;
                    });
                  },
                ),
              ],
            ),
          ),
        );
      }
    }