androidflutterdartdropdown

How to update text in an Flutter DropDownButton


I wanted to make a Dropdownbutton, where you could choose between two chategorys(Income or Expence) but with what i made, it only shows the defult state of the dropdown. If I try to click on Income to change it, it still shows Expence in the dropdown. After I click outside the Window for the creation of a new transaction and open it again with the add symbol, then it shows the previously selected Income choise. But I want it, so that directly when i press on Income, it changes the dropdown to income and i dont have to reopen the transaction creation.

Here is the code I used(It's not really organised and good, because it's my first flutter project):

import 'package:flutter/material.dart';
import 'package:spar_radar/services/database_service.dart';
import 'package:flutter/services.dart'; 
import 'package:date_format_field/date_format_field.dart';

class HomePage extends StatefulWidget{
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}


const List<String> types = <String>['Expence', 'Income'];


class _HomePageState extends State<HomePage> {

  final DatabaseService _databaseService = DatabaseService.instance;

  
  String? _transactionName = null;
  double? _transactionAmount = null;
  String? _transactionDate = null;
  String? _transactionType = types.first;
  @override 
  Widget build(Object context) {
    return Scaffold(

      floatingActionButton: _addTransactionButton(),
    ); 
  }

  Widget _addTransactionButton() {
    return FloatingActionButton(onPressed: () {
      showDialog(context: context, builder: (_) => AlertDialog(
        title: const Text('Add Transaction'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            TextField(
              onChanged: (value,) {
                setState(() {
                  _transactionName = value;
                });
              },
              decoration:  const InputDecoration(border: OutlineInputBorder(),
              labelText: "Name",
              hintText: 'Add The Name of the Transaction'
              ),
            ),
            TextField( 
              onChanged: (value) {
                setState(() {
                  _transactionAmount = double.parse(value);
                });
              },
              decoration: InputDecoration(labelText: "Amount",
              border: OutlineInputBorder(),
              hintText: 'Enter the amount here'), 
              keyboardType: TextInputType.number, 
              inputFormatters: <TextInputFormatter>[ 
              FilteringTextInputFormatter.digitsOnly
              ],
            ),
            DateFormatField(
              type: DateFormatType.type2,
              onComplete: (date){
                  setState(() {
                    _transactionDate = date.toString();
                  });
                }
            ),
            DropdownButton<String>(
                      value: _transactionType,
                      icon: const Icon(Icons.arrow_drop_down),
                      onChanged: (String? NewValue) {
                        setState(() {
                          _transactionType = NewValue;
                        });
                      },
                      items: types.map<DropdownMenuItem<String>>((String value) {
                        return DropdownMenuItem<String>(
                          value: value,
                          child: Text(value),
                        );
                      }).toList(),
            )
          ],
        )
      ));
    },
    child: const Icon(
      Icons.add,
      )
    );
    
  }

}

I hope someone can help me with this and thanks in advance!


Solution

  • To update state inside an AlertDialog, you can use StatefulBuilder like follows:

    Widget _addTransactionButton() {
        return FloatingActionButton(
          onPressed: () {
            showDialog(
              context: context,
              // add a StatefulBuilder here
              // the first argument is context, and the second argument is the function name to update the state with.
              // You can name this anything. Doesn't need to be setState only
              builder: (_) => StatefulBuilder(
                builder: (context, setState) {
                  return AlertDialog(
                      title: const Text('Add Transaction'),
                      content: Column(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          TextField(
                            onChanged: (
                              value,
                            ) {
                              setState(() {
                                _transactionName = value;
                              });
                            },
                            decoration: const InputDecoration(
                                border: OutlineInputBorder(),
                                labelText: "Name",
                                hintText: 'Add The Name of the Transaction'),
                          ),
                          TextField(
                            onChanged: (value) {
                              setState(() {
                                _transactionAmount = double.parse(value);
                              });
                            },
                            decoration: InputDecoration(
                                labelText: "Amount",
                                border: OutlineInputBorder(),
                                hintText: 'Enter the amount here'),
                            keyboardType: TextInputType.number,
                            inputFormatters: <TextInputFormatter>[
                              FilteringTextInputFormatter.digitsOnly
                            ],
                          ),
                          DropdownButton<String>(
                            value: _transactionType,
                            icon: const Icon(Icons.arrow_drop_down),
                            onChanged: (String? NewValue) {
                              setState(() {
                                _transactionType = NewValue;
                              });
                            },
                            items: types.map<DropdownMenuItem<String>>((String value) {
                              return DropdownMenuItem<String>(
                                value: value,
                                child: Text(value),
                              );
                            }).toList(),
                          )
                        ],
                      ));
                }
              ),
            );
          },
          child: const Icon(
            Icons.add,
          ),
        );
      }