1

I want to display send a request to API, to get data, display this data in a Form. Here is the code that I have.

import 'dart:io';

import 'package:flutter/material.dart';

import 'package:sample/models/item.model.dart';
import 'package:sample/models/unit.model.dart';
import 'package:sample/services/unit.service.dart';

class ItemDialog extends StatefulWidget {

  Item? item;

  ItemDialog.add({super.key}) {
    item = Item();
  }

  ItemDialog.edit(this.item, {super.key}) {
    item = item;
  }

  @override
  State<ItemDialog> createState() => _ItemDialogState(item);
}

class _ItemDialogState extends State<ItemDialog> {
  Item? item;
  _ItemDialogState(this.item);


  final _formKey = GlobalKey<FormState>();

  late Future<List<Unit>> unitList;
  Unit? unit;

  AppBar _createAppBar(BuildContext context) {
    return AppBar(
      title: widget.item?.name == null
          ? const Text("Add new item")
          : Text("Edit item ${widget.item?.name}"),
      actions: [
        ElevatedButton(
          child: const Text("Save"),
          onPressed: () {
            if (_formKey.currentState!.validate()) {
              setValueFromForm();
              Navigator.of(context).pop(item);
            }
          },
        )
      ],
    );
  }

  @override
  void initState() {
    super.initState();
    setInitialValue();
  }

  setInitialValue() {
    getAllData(widget.item!);
  }

  getAllData(Item item) {
    unitList = getAllUnits(item.house!.id);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: _createAppBar(context),
      body: SingleChildScrollView(
        child: Center(
          child: Column(
            children: [
              Padding(
                padding: const EdgeInsets.only(left: 10, right: 10),
                child: Form(
                  key: _formKey,
                  child: Column(
                    children: [
                      FutureBuilder(
                        future:unitList,
                        builder: (BuildContext context, AsyncSnapshot snapshot) {
                          return snapshot.hasData
                              ? Container(
                            child: DropdownButton<Unit>(
                              hint: Text('Make a selection'),
                              items: snapshot.data.map<DropdownMenuItem<Unit>>((item) {
                                return DropdownMenuItem<Unit>(
                                  value: item,
                                  child: Text(item.title),
                                );
                              }).toList(),
                              onChanged: (value) {
                                setState(() {
                                  unit = value;
                                  print(value);
                                });
                              },
                            ),
                          )
                              : Container(
                            child: Center(
                              child: Text('Loading...'),
                            ),
                          );
                        },
                      ),
                    ],
                  ),
                ),
              )
            ],
          )
        )
      ),
    );
  }
}

I am getting the following error:

type 'List' is not a subtype of type 'Future<List>' of 'function result'

Future<List<Unit>> getAllUnits(String? id) async {
  final response = await getDio()
      .get('/unit/house/$id');
  if (response.statusCode == 200) {
    List<Unit> list =  List<Unit>.from(response.data.map((item) => Unit.fromJson(item)).toList());
    return list;
  } else {
    throw Exception('Failed to load data');
  }
}

There are may other textfields as well as more date pickers etc. However I have removed all of this for ease of readability. Any help is appreciated.

1 Answers1

0

I have updated the component to be as below which is working fine.

DropdownButtonFormField2(
                        decoration: const InputDecoration(
                          isDense: true,
                          contentPadding: EdgeInsets.zero,
                        ),
                          isExpanded: true,
                          hint: const Text(
                            'Select unit',
                            style: TextStyle(
                                fontSize: 14),
                          ),
                          value: unit,
                          items: unitList.map((item) => DropdownMenuItem<Unit>(
                            value: item,
                            child: Text(
                              '${item.name}',
                              style: const TextStyle(
                                fontSize: 14,
                              ),
                            ),
                          )).toList(),
                          validator: (value) {
                            if (value == null) {
                              return 'Please select unit.';
                            }
                            return null;
                          },
                          onChanged: (value) {
                            newItem?.unit = (value as Unit).id;
                            item?.unit = value as Unit;
                          },
                          buttonStyleData: const ButtonStyleData(
                            height: 60,
                            padding: EdgeInsets.only(left: 20, right: 10),
                          ),
                          iconStyleData: const IconStyleData(
                            iconSize: 30,
                          ),
                          dropdownStyleData: DropdownStyleData(
                            decoration: BoxDecoration(
                              borderRadius: BorderRadius.circular(15),
                              color: darkThemePreference.darkOrLightGrey(context),
                            ),
                          ),
                        )

This should work fine.