Search code examples
fluttersetstate

Flutter setState not updating a particular widget


I am using multi_select_flutter to show multi chips in my flutter project. However, am trying to add more items to the chip with data loaded from my api while the user is searching but it doesn't update the state of the multi chip widget. Here is my full code.

Even when I hot reload, it does not update itself. The only way I can manually enforce a refresh update is to re-ad the widget and reload consecutively. Any information as to why this strange behavior happens?

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

  @override
  _MultiChoiceComponentState createState() => _MultiChoiceComponentState();
}

class _MultiChoiceComponentState extends State<MultiChoiceComponent> {
  ApiMethods apiMethods;

  TextEditingController searchController = TextEditingController();
  List<MultiSelectItem<dynamic>> labels = [];
  final TextEditingController textEditingController = TextEditingController();
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    apiMethods = new ApiMethods(context: context);
  }
  @override
  Widget build(BuildContext context) {
    return ListView(
      shrinkWrap: true,
      children: [
        Container(
          padding: EdgeInsets.symmetric(horizontal: 16),
          child: Text(
            'Search and select as many symptoms been experienced, it helps with a more accurate diagnosis',
            textAlign: TextAlign.start,
            style: TextStyle(
              fontSize: 14,
              height: 1.8,
              fontWeight: FontWeight.w400,
              fontFamily: 'Euclid',
              color: AppColors.grey1,
            ),
          ),
        ),
        SizedBox(
          height: 20,
        ),
        Container(
          padding: EdgeInsets.symmetric(horizontal: 16,),
          // height: maxLines * 50.0,
          child: TextField(
            controller: textEditingController,
            cursorColor: Colors.black26,
            onChanged: (val){
              if(val!=""){
                searchSymptoms(val);
              }
            },
            decoration: InputDecoration(
                filled: true,
                hintStyle: TextStyle(
                  fontSize: 14,
                  height: 1.6,
                  fontWeight: FontWeight.w400,
                  fontFamily: 'Euclid',
                  color: AppColors.grey1,
                ),
                hintText: "Search for a symptom/illness",
                fillColor: Colors.white,
                contentPadding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 14),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                ),
                focusedBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                ),
                enabledBorder: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(12.0),
                  borderSide: BorderSide(color: AppColors.textColor.withOpacity(0.5)),
                )),
          ),
        ),
        MultiSelectChipField(
          scroll: false,
          decoration: BoxDecoration(
            border: Border.all(color: Colors.transparent, width: 1.8),
          ),
          showHeader: false,
          selectedTextStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            fontFamily: 'Euclid',
            color: Colors.white,
          ),
          chipShape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(
              Radius.circular(12),
            ),
          ),
          selectedChipColor: AppColors.customGreen,
          chipColor: Colors.white,
          textStyle: TextStyle(
            fontSize: 12.5,
            height: 1.8,
            fontWeight: FontWeight.w400,
            fontFamily: 'Euclid',
            color: AppColors.textColor,
          ),
          items: labels,
          onTap: (value) {
            ///add symptoms to list
            print(value);
            selectedSymptoms = value as List<Conditions>;
          },
        ),
      ],
    );
  }
  Future<void> searchSymptoms(String searchQuery) async {
    List<dynamic> _data =  await apiMethods.searchConditions(symptomCheckerAge, searchQuery);
    conditions = Conditions.fromJsonList(_data);
    labels = conditions.map((e) => MultiSelectItem(e, e.label)).toList();
    setState(() {});
  }
}

Solution

  • I tried this given Chip Widget with custom data and it is working properly.. Meaning the items that I am adding on pressed are being added to the new list. Take a look and try out the few changes and see if that works for you

    class _MyHomePageState extends State<MyHomePage> {
        static List<Animal> _animals = [
        Animal(id: 1, name: "Lion"),
        Animal(id: 2, name: "Flamingo"),
        Animal(id: 3, name: "Hippo"),
        Animal(id: 4, name: "Horse"),
        Animal(id: 5, name: "Tiger"),
        Animal(id: 6, name: "Penguin"),
        Animal(id: 7, name: "Spider"),
        Animal(id: 8, name: "Snake"),
        Animal(id: 9, name: "Bear"),
        Animal(id: 10, name: "Beaver"),
        Animal(id: 11, name: "Cat"),
        Animal(id: 12, name: "Fish"),
        Animal(id: 13, name: "Rabbit"),
        ];
        dynamic _items = _animals
          .map((animal) => MultiSelectItem<Animal>(animal, animal.name))
          .toList();
        @override
        Widget build(BuildContext context) {
        return new Scaffold(
          backgroundColor: Colors.white,
          appBar: new AppBar(
            title: new Text('Hello'),
          ),
          body: ListView(
            scrollDirection: Axis.vertical,
            physics: NeverScrollableScrollPhysics(),
            children: [
              Container(
                child: MultiSelectChipField(
                  scroll: false,
                  decoration: BoxDecoration(
                    border: Border.all(color: Colors.transparent, width: 1.8),
                  ),
                  showHeader: false,
                  selectedTextStyle: TextStyle(
                    fontSize: 12.5,
                    height: 1.8,
                    fontWeight: FontWeight.w400,
                    color: Colors.blue,
                  ),
                  chipShape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.all(
                      Radius.circular(12),
                    ),
                  ),
                  selectedChipColor: Colors.green,
                  chipColor: Colors.yellow,
                  textStyle: TextStyle(
                    fontSize: 12.5,
                    height: 1.8,
                    fontWeight: FontWeight.w400,
                    color: Colors.black,
                  ),
                  items: _items,
                  onTap: (value) {
                    ///add symptoms to list
                    print(value);
                  },
                ),
              ),
              ElevatedButton(
                  onPressed: () {
                    _items.add(MultiSelectItem<Animal>(
                        Animal(id: 27, name: 'name'), 'new'));
                    setState(() {});
                  },
                  child: Text('Add'))
            ],
          ),
          );
         }
        }
    
         class Animal {
          final int id;
          final String name;
    
        Animal({
        required this.id,
        required this.name,
        });
       }