Search code examples
flutterdartbloc

Flutter - How to implement a Dropdown List using BloC?


I'd like to add a Dropdown list containing "names" in my application instead of a TextField as I have in the code below. How can I do this using BloC?

class PersonPage extends StatefulWidget {

  PersonPage(this.person);
  final Person person;

  @override
  _PersonPageState createState() => _PersonPageState();
}

class Names{
  const Item(this.name);
  final String name;
}

class _PersonPageState extends State<PersonPage> {
  Item selectedUser;
  List<Item> names = <Names>[
   const Item('Thomas'),
   const Item('John'),
   const Item('Mary'),
   const Item('Lukas'),
  ];
 TextEditingController _nameController;

 final _bloc = PersonBloc();

 @override
 void initState() {

  _bloc.setPerson(widget.person);
  _nameController = TextEditingController(text: widget.person.name);

  super.initState();
 }
@override
void dispose() {
 _nameController.dispose();
 super.dispose();
}

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text("MyApp"),
    ),
    body: Container(
      child: Padding(
        padding: const EdgeInsets.all(8.0),
        child: ListView(
          children: <Widget>[             
            Container(
              child: TextField(
                decoration: InputDecoration(labelText: "Name"),
                controller: _nameController,
                onChanged: _bloc.setName,
              ),
            ),
            Container(
              height: 20,
            ),              
            RaisedButton(
              child: Text("Save"),
              onPressed: () {
                if (_bloc.insertOrUpdate()) {
                  Navigator.pop(context);
                }
              },
            )
          ],
        ),
      ),
    ),
  );
}

Thanks.


Solution

  • I'll give to you an example and you try to apply in your code

    class _PersonPageState extends State<PersonPage> {
      final _bloc = PersonBloc();
    
      @override
      void initState() {
    
        _bloc.setPerson(widget.person);
        _nameController = TextEditingController(text: widget.person.name);
    
       super.initState();
      }
    
      @override
      void dispose() {
        _nameController.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
      return Scaffold(
        appBar: AppBar(
          title: Text("MyApp"),
        ),
        body: Container(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListView(
              children: <Widget>[             
                StreamBuilder(
                  stream: bloc.outName,
                  builder: (context, snapshot) {
                    if (!snapshot.hasData)
                      return Container();
    
                    return DropdownButton(
                      hint: Text("Names"),
                      value: snapshot.data,
                      items: bloc.names.map((item) {
                        return DropdownMenuItem(
                          value: item,
                          child: Row(children: <Widget>[Text(item),]),
                        );
                      }).toList(),
                      onChanged: bloc.inName,
                    );
                  },
                ),
                Container(
                  height: 20,
                ),              
                RaisedButton(
                  child: Text("Save"),
                  onPressed: () {
                    if (_bloc.insertOrUpdate()) {
                      Navigator.pop(context);
                    }
                  },
                )
              ],
            ),
          ),
        ),
      );
    }
    

    Change your names list to your BLoC, and create the name BehaviorSubject

    PersonBloc{
    
      List<String> names = ['Thomas', 'John', 'Mary', 'Lukas'];
    
      final _name = BehaviorSubject<String>.seeded("");
      Stream<String> get outName  => _name.stream;
      Function(String) get inName => _name.sink.add;
      //TODO - Don't forget to dispose this _name
    
    }
    

    Now your _name has the selected name, and to get the name, you just need to do

    Person.name = _name.stream.value;
    

    This example can be improved, it's just a draft