skip to Main Content

I’m trying to fetch the names of countries from an API and display it in a drop-down box. I’m using the bloc library for state management.

Here’s my Code.

select_input_field.dart – Custom wrapper widget for DropdownButtonField

import 'package:flutter/material.dart';

class SelectInputField extends StatelessWidget {
  final String label;
  final List<String> options;
  final TextEditingController controller;
  final EdgeInsets padding;

  const SelectInputField(this.label, this.options,
      { Key? key,
        required this.controller,
        this.padding =
          const EdgeInsets.only(top: 8, bottom: 8, left: 30, right: 30)})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: padding,
      child: DropdownButtonFormField(
        decoration: InputDecoration(
            labelText: label,
            labelStyle: Theme.of(context).textTheme.bodyMedium,
            border: OutlineInputBorder(
              borderSide: BorderSide(
                color: Theme.of(context).primaryColorDark,
                width: 1,
              ),
            ),
            enabledBorder: OutlineInputBorder(
              borderSide: BorderSide(
                color: Theme.of(context).primaryColorDark,
                width: 1,
              ),
            ),
            focusedBorder: OutlineInputBorder(
              borderSide: BorderSide(
                color: Theme.of(context).colorScheme.secondary,
                width: 1,
              ),
            ),
            fillColor: Theme.of(context).primaryColorLight),
        style: Theme.of(context).textTheme.bodyMedium,
        items: options.map((String value) {
          print(value);
          return DropdownMenuItem<String>(
            value: value,
            child: Text(value),
          );
        }).toList(),
        onChanged: (String? value) {
          controller.text = value ?? '';
        },
      ),
    );
  }
}

This is the method I’m using to build it.

  Widget _countriesDropDown(BuildContext context, TextEditingController controller){
    return BlocProvider(
      create: (context) => _signupBloc,
      child: BlocBuilder<SignupBloc,SignupState>(
        buildWhen: ((previous, current) => previous is! Loaded && current is Loaded),
        builder: (context, state){
          if (state is Initial){
            _signupBloc.add(LoadEvent());
          }
          else if (state is Loaded){
              countries = state.countries;
              return SelectInputField("Country", countries, controller: controller);
          }
          return CircularProgressIndicator(color: Theme.of(context).colorScheme.secondary,);

        },
      )

    );
  }

And my bloc class is as follows.

class SignupBloc extends Bloc<SignupEvent, SignupState> {
  static const String countriesUrl = "https://api.first.org/data/v1/countries";

  SignupBloc() : super(Initial()) {

    on<LoadEvent>((event, emit) async{
      emit(Loading());

      List<String> countries = [];

      try{
        final response = await http.get(Uri.parse(countriesUrl));
        if(response.statusCode == 200){
          var responseJson = jsonDecode(response.body);
          responseJson['data'].values.forEach((element) {
           countries.add(element['country']);
          });
          emit(Loaded(countries));
        }
        else{
          emit(Failed("Error in getting data"));
        }
      }
      catch(e){
        print(e);
        emit(Failed("Failed to access internet. Try again later!"));
      }
    });
}

The error appears to look like this. I cannot understand where this error occurs

======== Exception caught by rendering library =====================================================
The following assertion was thrown during paint():
Tried to paint a RenderObject reentrantly.

The following RenderObject was already being painted when it was painted again: RenderPointerListener#c100e relayoutBoundary=up20 NEEDS-PAINT
...  needs compositing
...  parentData: <none> (can use size)
...  constraints: BoxConstraints(0.0<=w<=351.4, 0.0<=h<=Infinity)
...  size: Size(351.4, 64.0)
...  behavior: opaque
...  listeners: down, panZoomStart
Since this typically indicates an infinite recursion, it is disallowed.
The relevant error-causing widget was: 
  DropdownButtonFormField<String> DropdownButtonFormField:file:///D:/Projects/sem5/iblock/lib/widgets/forms/select_input_field.dart:20:14
When the exception was thrown, this was the stack: 
#0      RenderObject._paintWithContext.<anonymous closure> (package:flutter/src/rendering/object.dart:2693:9)
#1      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2706:6)
#2      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:239:13)
#3      RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#4      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)
#5      PaintingContext.paintChild (package:flutter/src/rendering/object.dart:239:13)
#6      RenderProxyBoxMixin.paint (package:flutter/src/rendering/proxy_box.dart:144:15)
#7      RenderObject._paintWithContext (package:flutter/src/rendering/object.dart:2796:7)

I need an explanation about what’s wrong with my code and how to fix this.

Output of flutter doctor

[√] Flutter (Channel stable, 3.3.2, on Microsoft Windows [Version 10.0.22621.608], locale en-US)
    • Flutter version 3.3.2 on channel stable at C:flutter
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision e3c29ec00c (3 weeks ago), 2022-09-14 08:46:55 -0500
    • Engine revision a4ff2c53d8
    • Dart version 2.18.1
    • DevTools version 2.15.0

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at C:UsersISHADAppDataLocalAndroidsdk
    • Platform android-32, build-tools 30.0.3
    • Java binary at: C:Program FilesAndroidAndroid Studiojrebinjava
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[√] Chrome - develop for the web
    • CHROME_EXECUTABLE = C:Program FilesBraveSoftwareBrave-BrowserApplicationbrave.exe

[√] Visual Studio - develop for Windows (Visual Studio Build Tools 2019 16.11.18)
    • Visual Studio at C:Program Files (x86)Microsoft Visual Studio2019BuildTools
    • Visual Studio Build Tools 2019 version 16.11.32802.440
    • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 2021.3)
    • Android Studio at C:Program FilesAndroidAndroid Studio
    • Flutter plugin can be installed from:
       https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
       https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[√] IntelliJ IDEA Ultimate Edition (version 2022.2)
    • IntelliJ at C:Program FilesJetBrainsIntelliJ IDEA 2022.1.2
    • Flutter plugin version 70.2.5
    • Dart plugin version 222.4167.21

[√] VS Code (version 1.71.2)
    • VS Code at C:UsersISHADAppDataLocalProgramsMicrosoft VS Code
    • Flutter extension version 3.48.0

[√] Connected device (3 available)
    • Windows (desktop) • windows • windows-x64    • Microsoft Windows [Version 10.0.22621.608]
    • Chrome (web)      • chrome  • web-javascript • unknown
    • Edge (web)        • edge    • web-javascript • Microsoft Edge 105.0.1343.53
    ! Device DRGGAM5890805202 is not authorized.
      You might need to check your device for an authorization dialog.

[√] HTTP Host Availability
    • All required HTTP hosts are available

• No issues found!

PS:
I’m not much familiar with Flutter/ bloc library.

3

Answers


  1. Chosen as BEST ANSWER

    Converting the SelectInputField to a StatefulWidget solved the issue. I think DropdownButtonFormField need to be rendered itself upon activities on it. So, StatelessWidget cannot rerender itself causing this problem.


  2. Not sure if you still having this issue but I had a similar issue and I added isExpanded: true to my DropdownButtonFormField which resolved the error. My problem was caused by the length of the words in my DropdownMenuItem. When I look at the response of your API call I see some very long names. I could be wrong though

    Login or Signup to reply.
  3. I got the same issue, and I am able to fix it.

    The issue is with the DropdownButtonFormField.
    It should have ‘value‘ property.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search