I am trying to make a screen with filter, and a search buttons, but whenever i select a text field the screen start searching, even if i haven't written anything yet, i am using a column with 2 textFields, none of them uses onChanged or onTap functions, after the textfields, there is a button, where i wanted to do the search, and after the button there's a future builder, where the info is suposed to show.
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: ctrl1,
keyboardType: TextInputType.number,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
decoration: const InputDecoration(
border: OutlineInputBorder(),
fillColor: Colors.white,
labelText: 'filter1',
floatingLabelBehavior: FloatingLabelBehavior.always,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: ctrl2,
decoration: const InputDecoration(
border: OutlineInputBorder(),
fillColor: Colors.white,
labelText: 'filter2',
floatingLabelBehavior: FloatingLabelBehavior.always,
),
),
)
Whenever i tap or change any of the text fields, apparently the state updates, forcing the search. How can i stop the textfields from updating the state of the Screen when tapped or changed?
I resolved the issue by using this variable Future<List<dynamic>?>? infoList;
as the future in FutureBuilder, and when the search button is pressed, i just update this var with the search function like this infoList = search(filter1.text, filter2.text);
.
class _WidgSttflState extends State<WidgSttfl> {
TextEditingController ctrl1 = TextEditingController(),
ctrl2 = TextEditingController();
PageController _pgView = PageController(initialPage: 0);
ExpansionTileController exp = ExpansionTileController();
Future<List<dynamic>?>? infoList;
Future<dynamic> buildData(filter1, filter2) async {
...
}
Future<List<dynamic>?> search(filter1, filter2) async {
return await buildData(filter1, filter2);
}
@override
void initState() {
infoList = Future.value([]);
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: 'title'
),
body: PageView(
controller: _pgView,
physics: const NeverScrollableScrollPhysics(),
children: [
...,
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Theme(
data: Theme.of(context).copyWith(
dividerColor: Colors.transparent,
),
child: ExpansionTile(
title: const Text('Filters'),
controller: exp,
initiallyExpanded: true,
leading: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () => _pgView.previousPage(
duration: const Duration(seconds: 1),
curve: Curves.easeInOutCubicEmphasized,
),
icon: const Icon(
Icons.arrow_back,
color: Colors.orange,
),
),
const VerticalDivider(
thickness: 1,
indent: 5,
endIndent: 5,
color: Colors.orange,
),
],
),
trailing: const Icon(Icons.filter_alt),
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: ctrl1,
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.digitsOnly
],
decoration: const InputDecoration(
border: OutlineInputBorder(),
fillColor: Colors.white,
labelText: 'filter1',
floatingLabelBehavior: FloatingLabelBehavior.always,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: ctrl2,
decoration: const InputDecoration(
border: OutlineInputBorder(),
fillColor: Colors.white,
labelText: 'filter2',
floatingLabelBehavior: FloatingLabelBehavior.always,
),
),
),
...,
SizedBox(
width: double.infinity,
child: Padding(
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
child: ElevatedButton(
onPressed: () {
setState(() {
infoList = search(filter1.text, filter2.text);
exp.collapse();
});
},
child: const Text(
'Search',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
),
],
),
),
const Divider(thickness: 2),
Expanded(
child: FutureBuilder(
future: infoList,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
} else if (snapshot.hasData) {
if (snapshot.data.isNotEmpty) {
return ListView.separated(
itemCount: snapshot.data.length,
separatorBuilder: (context, index) =>
const Divider(),
itemBuilder: (context, index) {
return ListTile(
title: Text(''),
subtitle: Text(''),
);
},
);
}
}
},
),
),
],
),
],
),
);
}
}