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((){});
}
- 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});
}