Home > Enterprise >  List data filter not showing and not working in Flutter
List data filter not showing and not working in Flutter

Time:07-06

I created a list element search. I get the list from the Internet. The data is all displayed, but when I want to use the _runFilter method, the data disappears and nothing happens. 1. How to make data search work? 2. When I open the page, my _foundAddressesInStationList is empty, but I initialize it and the data should be displayed, why is it not displayed? Thanks in advance.

  List<PublicChargingStationModel> stationsList = [];

  List<PublicChargingStationModel> _foundAddressesInStationList = [];

  @override
  void initState() {
    _loadStations();
    _foundAddressesInStationList = stationsList;
    super.initState();
  }

  void _runFilter(String enteredKeyword) {
    List<PublicChargingStationModel> resultAddressesInStationList = [];
    if (enteredKeyword.isEmpty) {
      resultAddressesInStationList = stationsList;
    } else {
      resultAddressesInStationList = stationsList
          .where((element) => element.address!
              .toLowerCase()
              .contains(enteredKeyword.toLowerCase()))
          .toList();
    }
    setState(
      () {
        _foundAddressesInStationList = resultAddressesInStationList;
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    final Size size = MediaQuery.of(context).size;
    final double paddingTop = MediaQuery.of(context).padding.top;

    return Container(
      width: size.width,
      height: size.height,
      child: _child(size, paddingTop),
    );
  } 

  void _loadStations() async {
    final StationCubit stationCubit = BlocProvider.of<StationCubit>(context);

    stationsList = await stationCubit.getPublicChargingStation();
  }
}

CodePudding user response:

In the init method you are calling your cubit which is asynchronous, but without waiting for the result you initialize the _foundAddressesInStationList with stationList which is empty. So, initialize the _foundAddressesInStationList in the load method like this.

  void _loadStations() async {
    final StationCubit stationCubit = BlocProvider.of<StationCubit>(context);
    stationsList = await stationCubit.getPublicChargingStation();
    _foundAddressesInStationList = stationsList;
    setState((){});
  }
  1. Filter should work fine. Do you have any warnings or errors? Do you have expected values in resultAddressesInStationList while filtering?

Edit: Alternate Approach for Filter:

stationsList.forEach((element) { 
    if(element.address!.toLowerCase().contains(enteredKeyword.toLowerCase())) {
      resultAddressesInStationList.add(element);
    }
  });
_foundAddressesInStationList = resultAddressesInStationList;
setState(() {});

The only place you added null check operator is element.address!. "Null check operator used on a null value" means the address should be null or should not exists.

Also try element["address"]

Edit 2:

You Search Widget like this should be:

class MySearchWidget extends StatefulWidget {
  MySearchWidget(
      {Key? key,
        required this.onChanged, this.isListClear})
      : super(key: key);

  final Function(String?) onChanged;
  final Function(bool)? isListClear;

  @override
  State<MySearchWidget> createState() => _MySearchWidget();
}

class _MySearchWidget extends State<MySearchWidget> {
  late FocusNode myFocusNode;
  final TextEditingController _textController = TextEditingController();

  @override
  void initState() {
    myFocusNode = FocusNode();
    super.initState();
  }

  @override
  void dispose() {
    myFocusNode.dispose();
    super.dispose();
  }

  _onBackPressed(context) {}

  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        IconButton(
          padding: EdgeInsets.zero,
          constraints: const BoxConstraints(),
          onPressed: () {
            _onBackPressed(context);
          },
          icon: Icon(Icons.arrow_left),
        ),
        Expanded(
          child: Container(
            alignment: Alignment.center,
            padding: const EdgeInsets.only(right: 14),
            child: TextFormField(
              controller: _textController,
              focusNode: myFocusNode,
              autofocus: true,
              onChanged: (value) => widget.onChanged(value),
              decoration: InputDecoration(
                suffixIcon: _textController.text.isNotEmpty
                    ? GestureDetector(
                  onTap: () {
                    _textController.clear();
                    widget.isListClear!(true);
                  },
                  child: Container(
                    width: 10,
                    height: 10,
                    alignment: Alignment.center,
                    child: Icon(Icons.clear),
                  ),
                )
                    : const SizedBox(),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

If not used like this, the change method of this widget will be called while initializing the widget and it will filter your data for the empty string which is unwanted and will also raise issues.

But the actual error is the null operator. I guess your PublicChargingStationModel class should have the 'address' property as not null.

So you should not use like

resultAddressesInStationList = stationsList
    .where((element) => element.address!
    .toLowerCase()
    .contains(enteredKeyword.toLowerCase()))
    .toList();

instead, use it like

resultAddressesInStationList = stationsList
    .where((element) => element.address
    .toLowerCase()
    .contains(enteredKeyword.toLowerCase()))
    .toList();

or change your model address property to nullable and keep your filter as it is now.

class PublicChargingStationModel{
  final String? address;

  PublicChargingStationModel({required this.address});
}
  • Related