2

I want to update dropdown items with setState when data received from api. Dropdown items not update even though widget is rebuilt. I can only get updated dropdown items after unfocus and focus. Please point me out if something wrong in my code..

Dropdown

import 'dart:async';
import 'package:eas/app/core/theme/colors.dart';
import 'package:eas/app/core/theme/theme.dart';
import 'package:eas/app/core/widgets/form_field_input.dart';
import 'package:flutter/material.dart';
import 'package:lottie/lottie.dart';

class AppAsyncDropdown extends StatefulWidget {
  final double width;
  final String hint;
  final bool loading;
  final List<DropdownMenuItem> items;
  final Function(String search) onChanged;
  const AppAsyncDropdown({
    Key? key,
    required this.width,
    required this.hint,
    required this.loading,
    required this.items,
    required this.onChanged,
  }) : super(key: key);

  @override
  State<AppAsyncDropdown> createState() => _AppAsyncDropdownState();
}

class _AppAsyncDropdownState extends State<AppAsyncDropdown> {
  Timer? _timer;

  void debounceSearch(String search) {
    if (_timer != null) {
      _timer!.cancel();
    }
    _timer = Timer(
        const Duration(milliseconds: 400), (() => widget.onChanged(search)));
  }

  @override
  void dispose() {
    if (_timer != null) {
      _timer!.cancel();
    }
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    print('why.. ${widget.loading} - ${widget.items}');
    final items = [
      DropdownMenuItem(
        enabled: false,
        child: FormFieldInput(
          controller: TextEditingController(),
          width: widget.width,
          hintText: 'search product',
          onChanged: (value) => debounceSearch(value),
        ),
      ),
    ];
    if (widget.loading) {
      items.add(
        DropdownMenuItem(
          enabled: false,
          child: SizedBox(
            width: widget.width,
            child: Center(
                child: Lottie.asset(
              'assets/animation/search_loading.json',
              width: 150,
            )),
          ),
        ),
      );
    }
    if (widget.items.isNotEmpty) {
      items.addAll(widget.items);
    }
    return SizedBox(
      width: widget.width,
      child: DropdownButtonFormField<dynamic>(
        isExpanded: true,
        decoration: InputDecoration(
          hintText: widget.hint,
          hintStyle: AppTheme.of(context).subtitle4,
          border: const UnderlineInputBorder(
              borderSide: BorderSide(color: Colors.black)),
          focusedBorder: const UnderlineInputBorder(
            borderSide: BorderSide(color: AppColors.primary),
          ),
        ),
        items: items,
        onChanged: (dynamic e) {
          print('hii $e');
        },
      ),
    );
  }
}

I added debounce to prevent requesting on every keystroke.And by debugging with print and some ui changes, it is verified that states are updated..

Script That Update State

import 'dart:async';

import 'package:eas/app/core/layout/desktop/content_desktop.dart';
import 'package:eas/app/core/layout/desktop/header_desktop.dart';
import 'package:eas/app/core/layout/desktop/layout_desktop.dart';
import 'package:eas/app/core/theme/colors.dart';
import 'package:eas/app/core/theme/miscs.dart';
import 'package:eas/app/core/theme/sizedBoxes.dart';
import 'package:eas/app/core/theme/sizes.dart';
import 'package:eas/app/core/theme/theme.dart';
import 'package:eas/app/core/widgets/button.dart';
import 'package:eas/app/core/widgets/dropdown.dart';
import 'package:eas/app/core/widgets/dynamic_list.dart';
import 'package:eas/app/routes/app_pages.dart';
import 'package:flutter/material.dart';

class TransferStockForm extends StatefulWidget {
  const TransferStockForm({Key? key}) : super(key: key);

  @override
  State<TransferStockForm> createState() => _TransferStockFormState();
}

class _TransferStockFormState extends State<TransferStockForm> {
  Timer? _timer;
  List<DropdownMenuItem> _branchWarehouses = [];
  bool _isLoading = false;

  void updateBranchWarehouse(String search) {
    print('searched - $search');
    setState(() {
      _isLoading = true;
      _branchWarehouses = [];
    });
    _timer = Timer(
      const Duration(seconds: 2),
      () {
        setState(() {
          _isLoading = false;
          _branchWarehouses = const [
            DropdownMenuItem(
              value: '1',
              child: Text('one'),
            ),
            DropdownMenuItem(
              value: '2',
              child: Text('two'),
            ),
            DropdownMenuItem(
              value: '3',
              child: Text('three'),
            ),
          ];
        });
      },
    );
  }

  @override
  void dispose() {
    if (_timer != null) {
      _timer!.cancel();
    }

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: AppDesktopLayout(
          header: const AppDesktopHeader(
            title: "Transfer Stock",
            pageName: AppRoutes.transferStockForm,
            isFavourable: true,
          ),
          currentNavi: AppRoutes.home,
          content: AppDesktopContent(
            child: Container(
              padding: const EdgeInsets.all(AppSizes.md),
              child: Container(
                padding: const EdgeInsets.all(AppSizes.md),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: const BorderRadius.all(
                    Radius.circular(AppSizes.sm),
                  ),
                  boxShadow: [
                    AppThemeMiscs.shadow2,
                  ],
                ),
                child: LayoutBuilder(builder: (context, constraint) {
                  return Row(
                    children: [
                      SizedBox(
                        width: constraint.maxWidth * 0.35,
                        height: constraint.maxHeight,
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'To',
                              style: AppTheme.of(context).headline3,
                            ),
                            AppSizeBoxes.sm,
                            AppAsyncDropdown(
                              width: constraint.maxWidth * 0.35,
                              hint: 'select branch or warehouse to transfer to',
                              loading: _isLoading,
                              items: _branchWarehouses,
                              onChanged: (String search) =>
                                  updateBranchWarehouse(search),
                            ),
                            AppSizeBoxes.md,
                            Button(onPressed: () {}, text: 'Transfer'),
                          ],
                        ),
                      ),
                      const Expanded(
                          child: DynamicList(
                        type: 'stock',
                      )),
                    ],
                  );
                }),
              ),
            ),
          )),
    );
  }
}

faked api response with timer

0 Answers0