Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a dropdown with objects in Flutter

Tags:

flutter

dart

I try to create a dropdown and to populate it with few objects which represents few servers from where the user can pick one, but when I run the app I'm getting an error saying:

The following assertion was thrown building DropdownWidget(dirty, state: _DropdownWidgetState#1f58f): There should be exactly one item with [DropdownButton]'s value: Instance of 'ServerModel'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value

Can you please help me to identify what I'm doing wrong in my code?

import 'package:flutter/material.dart';
​
class ServerSettingsPage extends StatefulWidget {
  @override
  _ServerSettingsPageState createState() => _ServerSettingsPageState();
}
​
class _ServerSettingsPageState extends State<ServerSettingsPage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
      title: Text("Server Settings")),
      body: _buildUI(),
    );
  }
​
  Widget _buildUI() {
    return Padding(
      padding: const EdgeInsets.fromLTRB(0, 20, 0, 0),
      child: Center(
        child: Column(
          children: <Widget>[
            Text(
              'Select a server:',
              style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
            ),
            DropdownWidget(),
          ],
        ),
      ),
    );
  }
}
​
class DropdownWidget extends StatefulWidget {
  DropdownWidget({Key key}) : super(key: key);
​
  @override
  _DropdownWidgetState createState() => _DropdownWidgetState();
}
​
class _DropdownWidgetState extends State<DropdownWidget> {
  ServerModel dropdownValue =
      ServerModel(name: 'Default', url: 'https://defaultServer.com/');
​
  @override
  Widget build(BuildContext context) {
    return DropdownButton<ServerModel>(
      value: dropdownValue,
      icon: Icon(Icons.arrow_downward),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(color: Colors.purple[700]),
      underline: Container(
        height: 2,
        color: Colors.purple[700],
      ),
      onChanged: (ServerModel newServer) {
        setState(() {
          dropdownValue = newServer;
        });
      },
      items: <ServerModel>[
        ServerModel(name: 'Default', url: 'https:defaultServer.com/'),
        ServerModel(name: 'Alpha', url: 'https://alphaServer.com/'),
        ServerModel(name: 'Beta', url: 'https://betaServer.com/'),
      ].map<DropdownMenuItem<ServerModel>>((ServerModel server) {
        return DropdownMenuItem<ServerModel>(
          value: server,
          child: Text(server.name, style: TextStyle(fontSize: 20)),
        );
      }).toList(),
    );
  }
}

And here is the ServerModel class:

class ServerModel {
  ServerModel({this.name, this.url});
​
  ServerModel.empty() {
    this.name = null;
    this.url = null;
  }
​
  String name;
  String url;
}

Many thanks for reading this post.

like image 445
Florentin Lupascu Avatar asked Sep 02 '26 22:09

Florentin Lupascu


1 Answers

There should be exactly one item with [DropdownButton]'s value: Instance of 'ServerModel'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value

This is happening because selected value inside the dropdown has to point to an existing list item (and obviously there shouldn't be any duplicates in that list). The way you've set it up right now is that the list of ServerModel is being generated during your widget build time and once it is built there no reference to the list inside the state of the widget. I hope my answer is clear enough, also take a look at correct code bellow:

class _DropdownWidgetState extends State<DropdownWidget> {
  List<ServerModel> serverModels = <ServerModel>[
    ServerModel(name: 'Default', url: 'https:defaultServer.com/'),
    ServerModel(name: 'Alpha', url: 'https://alphaServer.com/'),
    ServerModel(name: 'Beta', url: 'https://betaServer.com/'),
  ];
  ServerModel selectedServer;

  @override
  initState() {
    super.initState();
    selectedServer = serverModels[0];
  }

  @override
  Widget build(BuildContext context) {
    return DropdownButton<ServerModel>(
      value: selectedServer,
      icon: Icon(Icons.arrow_downward),
      iconSize: 24,
      elevation: 16,
      style: TextStyle(color: Colors.purple[700]),
      underline: Container(
        height: 2,
        color: Colors.purple[700],
      ),
      onChanged: (ServerModel newServer) {
        setState(() {
          selectedServer = newServer;
        });
      },
      items: serverModels.map((ServerModel map) {
        return new DropdownMenuItem<ServerModel>(
            value: map, child: Text(map.name));
      }).toList(),
    );
  }
}

Tested, working interactive answer on dartpad: https://dartpad.dev/153bad9baac64382e27bc41cdc8131c9

like image 135
Uroš Avatar answered Sep 05 '26 14:09

Uroš



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!