How to combine DropdownMenu and AppLocalization in Flutter within context?

542

You can copy paste run full code below
You can use package https://pub.dev/packages/equatable and extend Equatable
code snippet

import 'package:equatable/equatable.dart';
...
class KeyValueRecordType extends Equatable {
  String key;
  String value;

  KeyValueRecordType({this.key, this.value});

  @override
  List<Object> get props => [key, value];
}

working demo

enter image description here

full code

import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';

class KeyValueRecordType extends Equatable {
  String key;
  String value;

  KeyValueRecordType({this.key, this.value});

  @override
  List<Object> get props => [key, value];
}

class AddNewTrainingForm extends StatefulWidget {
  @override
  AddNewTrainingFormState createState() => AddNewTrainingFormState();
}

class AddNewTrainingFormState extends State<AddNewTrainingForm> {
  KeyValueRecordType recordType;

  @override
  Widget build(BuildContext context) {
    List<KeyValueRecordType> recordTypes = <KeyValueRecordType>[
      KeyValueRecordType(key: "dressage", value: 'dressage'),
      KeyValueRecordType(key: "cavaletti", value: 'cavaletti'),
      KeyValueRecordType(key: "jumping", value: 'jumping'),
      KeyValueRecordType(key: "hacking", value: 'hacking'),
      KeyValueRecordType(key: "groundwork", value: 'groundwork'),
      KeyValueRecordType(key: "competition", value: 'competition'),
      KeyValueRecordType(key: "other", value: 'other'),
    ];

    return SafeArea(
      child: Scaffold(
          body: Container(
        child: Theme(
          data: Theme.of(context).copyWith(
            canvasColor: Colors.white,
          ),
          child: DropdownButton<KeyValueRecordType>(
            value: recordType,
            onChanged: (KeyValueRecordType value) {
              setState(() {
                recordType = value; //show selected value
              });
            },
            items: recordTypes
                .map<DropdownMenuItem<KeyValueRecordType>>(
                    (recordType) => new DropdownMenuItem<KeyValueRecordType>(
                          child: Text(recordType.value),
                          value: recordType,
                        ))
                .toList(),
          ),
        ),
      )),
    );
  }
}

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: AddNewTrainingForm(),
    );
  }
}
Share:
542
marhyno
Author by

marhyno

Updated on December 24, 2022

Comments

  • marhyno
    marhyno over 1 year

    I am having trouble working with dropdown menu in flutter together with AppLocalization. I have implemented automatic localization based on user selected language in phone settings. It works good until I want to implement also dropdown menu with localised values. When I render dropdown menu it works but after I select value a get an error like this Flutter: There should be exactly one item with [DropdownButton]'s value, Please note I need appLocalization in the KeyValueRecords list,

    import 'package:MyHorse.sk/app_localizations.dart';
    
    class AddNewTrainingFormState extends State<AddNewTrainingForm> {
    
      KeyValueRecordType recordType;
    
      @override
      Widget build(BuildContext context) {
        List<KeyValueRecordType> recordTypes = <KeyValueRecordType>[
          KeyValueRecordType(
              key: "dressage",
              value: AppLocalizations.of(context).translate('dressage')),
          KeyValueRecordType(
              key: "cavaletti",
              value: AppLocalizations.of(context).translate('cavaletti')),
          KeyValueRecordType(
              key: "jumping",
              value: AppLocalizations.of(context).translate('jumping')),
          KeyValueRecordType(
              key: "hacking",
              value: AppLocalizations.of(context).translate('hacking')),
          KeyValueRecordType(
              key: "groundwork",
              value: AppLocalizations.of(context).translate('groundwork')),
          KeyValueRecordType(
              key: "competition",
              value: AppLocalizations.of(context).translate('competition')),
          KeyValueRecordType(
              key: "other", value: AppLocalizations.of(context).translate('other')),
        ];
    
            return Scaffold(
                  body: Container(
                  child: Theme(
                    data: Theme.of(context).copyWith(
                      canvasColor: Colors.black,
                    ),
                    child: DropdownButton<KeyValueRecordType>(
                      value: recordType,
                      onChanged: (KeyValueRecordType value) {
                        setState(() {
                          recordType = value; //show selected value
                        });
                      },
                      items: recordTypes
                          .map<DropdownMenuItem<KeyValueRecordType>>(
                              (recordType) =>
                                  new DropdownMenuItem<KeyValueRecordType>(
                                    child: Text(recordType.value),
                                    value: recordType,
                                  ))
                          .toList(),
                    ),
                  ),
    
    class KeyValueRecordType {
      String key;
      String value;
    
      KeyValueRecordType({this.key, this.value});
    }
    

    So the error is:

    There should be exactly one item with [DropdownButton]'s value: Instance of 'KeyValueRecordType'.
    I/flutter ( 9900): Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
    I/flutter ( 9900): 'package:flutter/src/material/dropdown.dart':
    I/flutter ( 9900): Failed assertion: line 834 pos 15: 'items == null || items.isEmpty || value == null ||
    I/flutter ( 9900):               items.where((DropdownMenuItem<T> item) {
    I/flutter ( 9900):                 return item.value == value;
    I/flutter ( 9900):               }).length == 1'
    

    I tried different approaches, when I specify recordType.key within onchanged I get error that this key does not exist. I tried also putting the List in FutureBuilder and in separate function, neither worked. As I need Context I cannot put it outside of the build method.