[FIXED] Ändern Sie dynamisch den Wert eines DropdownButton basierend auf dem Wert eines anderen DropdownButton [FLUTTER]

Ausgabe

Ich hoffe, es geht dir gut. Ich habe ein kleines Problem, ich möchte den Wert eines DropdownButton basierend auf dem Wert eines anderen DropdownButton dynamisch ändern.

Nun, ich werde erklären, wo ich stehe und was das Problem ist:

Zuerst habe ich eine Liste von StudyCycle mit 3 Elementen;

final _studyCycles = const <StudyCycle>[
    StudyCycle(cycle: Cycles.elementary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.cp,
      ClassroomsLevels.ce1,
      ClassroomsLevels.ce2,
      ClassroomsLevels.cm1,
      ClassroomsLevels.cm2,
    ]),
    StudyCycle(cycle: Cycles.primary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.sixth,
      ClassroomsLevels.fifth,
      ClassroomsLevels.fourth,
      ClassroomsLevels.third,
    ]),
    StudyCycle(cycle: Cycles.secondary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.second,
      ClassroomsLevels.first,
      ClassroomsLevels.terminal,
    ])
  ];

Diese StudyCycle- Liste wird verwendet, um die erste Dropdown-Schaltfläche zu erstellen

 DropdownButton<StudyCycle>(
          value: _selectedStudyCycle,
          items: List<DropdownMenuItem<StudyCycle>>.generate(
            _studyCycles.length,
            (index) => DropdownMenuItem<StudyCycle>(
              value: _studyCycles[index],
              child: Text(_studyCycles[index].cycle.toString()),
            ),
          ),
          hint: const Text('Your Study Cycle'),
          onChanged: (StudyCycle? studyCycle) {
            if (studyCycle != _selectedStudyCycle) {
              if (_selectedStudyCycle != null) setState(() => _selectedStudyCycle = null);

              if (studyCycle != null) setState(() => _selectedStudyCycle = studyCycle);
            }
          },
        )

Und durch Auswahl eines StudyCycle aus dem StudyCycles-Dropdown können Werte eines anderen Dropdown-Buttons erstellt werden, der diesmal die ClassroomsLevels des StudyCycle enthält, der derzeit im StudyCycles-Dropdown ausgewählt ist (so weit, so gut).

    DropdownButton<ClassroomsLevels>(
      hint: const Text('Select your classroom'),
      value: _selectedClassroom,
      items: _selectedStudyCycle == null
          ? []
          : List<DropdownMenuItem<ClassroomsLevels>>.generate(
              _selectedStudyCycle!.classrooms.length,
              (index) => DropdownMenuItem<ClassroomsLevels>(
                value: _selectedStudyCycle!.classrooms[index],
                child: Text(_selectedStudyCycle!.classrooms[index].toString()),
              ),
            ),
      onChanged: (ClassroomsLevels? classroom) => setState(() => _selectedClassroom = classroom),
    )

Das Problem tritt auf, wenn ein ClassroomLevel ausgewählt ist und ich StudyCycle ändere, erhalte ich diesen Fehler:

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

Ich habe mein Bestes versucht, um das Problem zu lösen, aber ich konnte es nicht (und ich verstehe nicht wirklich warum), also verlasse ich mich auf Sie. Können Sie mir helfen, den Fehler zu verstehen und ihn zu beheben?

Der vollständige Code

import 'package:flutter/material.dart';

class MyHomePage2 extends StatefulWidget {
  const MyHomePage2({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage2> createState() => _MyHomePage2State();
}

class _MyHomePage2State extends State<MyHomePage2> {
  final _studyCycles = const <StudyCycle>[
    StudyCycle(cycle: Cycles.elementary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.cp,
      ClassroomsLevels.ce1,
      ClassroomsLevels.ce2,
      ClassroomsLevels.cm1,
      ClassroomsLevels.cm2,
    ]),
    StudyCycle(cycle: Cycles.primary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.sixth,
      ClassroomsLevels.fifth,
      ClassroomsLevels.fourth,
      ClassroomsLevels.third,
    ]),
    StudyCycle(cycle: Cycles.secondary, classrooms: <ClassroomsLevels>[
      ClassroomsLevels.second,
      ClassroomsLevels.first,
      ClassroomsLevels.terminal,
    ])
  ];

  StudyCycle? _selectedStudyCycle;

  ClassroomsLevels? _selectedClassroom;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(widget.title)),
      body: SizedBox(
        width: MediaQuery.of(context).size.width,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            DropdownButton<StudyCycle>(
              value: _selectedStudyCycle,
              items: List<DropdownMenuItem<StudyCycle>>.generate(
                _studyCycles.length,
                (index) => DropdownMenuItem<StudyCycle>(
                  value: _studyCycles[index],
                  child: Text(_studyCycles[index].cycle.toString()),
                ),
              ),
              hint: const Text('Your Study Cycle'),
              onChanged: (StudyCycle? studyCycle) {
                if (studyCycle != _selectedStudyCycle) {
                  if (_selectedStudyCycle != null) setState(() => _selectedStudyCycle = null);

                  if (studyCycle != null) setState(() => _selectedStudyCycle = studyCycle);
                }
              },
            ),

            //

            DropdownButton<ClassroomsLevels>(
              hint: const Text('Select your classroom'),
              value: _selectedClassroom,
              items: _selectedStudyCycle == null
                  ? []
                  : List<DropdownMenuItem<ClassroomsLevels>>.generate(
                      _selectedStudyCycle!.classrooms.length,
                      (index) => DropdownMenuItem<ClassroomsLevels>(
                        value: _selectedStudyCycle!.classrooms[index],
                        child: Text(_selectedStudyCycle!.classrooms[index].toString()),
                      ),
                    ),
              onChanged: (ClassroomsLevels? classroom) => setState(() => _selectedClassroom = classroom),
            ),
          ],
        ),
      ),
    );
  }
}

class StudyCycle {
  final Cycles cycle;

  final List<ClassroomsLevels> classrooms;

  final String? description;

  final int? iconCodePoint;

  const StudyCycle({
    required this.cycle,
    required this.classrooms,
    this.description,
    this.iconCodePoint,
  });
}

enum Cycles { elementary, primary, secondary, secondaryTechnique }

enum ClassroomsLevels {
  cp,
  ce1,
  ce2,
  cm1,
  cm2,
  sixth,
  fifth,
  fourth,
  third,
  second,
  first,
  terminal,
  mechanical,
  electronic,
  electricity,
  inEngineering,
  secretariat,
  accounting,
  economy,
  agr1,
  agr2,
  agr3,
}

DANKE!

Lösung

Der Grund für den Fehler ist, dass der Wert _selectedClassroomin Ihrem zweiten Dropdown-Menü nicht in der neuen Klassenzimmerliste vorhanden ist, _selectedStudyCycle!.classroomssobald Sie den Wert des ersten Dropdown-Menüs ändern. Setzen Sie einfach den Wert Ihres zweiten Dropdowns in der setStateMethode zurück:

if (studyCycle != null) {
 setState(() {
 // Add this line
 _selectedClassroom = null;
 _selectedStudyCycle = studyCycle;
});
}


Beantwortet von –
hnnngwdlch


Antwort geprüft von –
Dawn Plyler (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like