Query not working correctly when searching ListView with TextFormField - flutter

I am listing records from Firebase Firestore with ListView.builder. I convert the incoming records to Model and list them.
I made a search option and I'm trying to make a filtering system for it. I want to filter by nameSurname search, city and district value.
I wrote a code like this:
StreamBuilder(
stream: db
.collection("NeedClothesPeople")
.snapshots(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
final searchText = searchController.text.trim().toLowerCase();
final List<NeedClothesPeopleModel> data = snapshot.data!.docs
.map((e) => NeedClothesPeopleModel.fromDocument(e))
.where((e) =>
searchText.isEmpty ||
e.nameSurname!.toLowerCase().contains(searchText) &&
selectedCity.isEmpty ||
e.city == selectedCity && selectedDistrict.isEmpty ||
e.district == selectedDistrict) // filter
.toList();
return Column(
children: [
const SizedBox(height: 10),
SizedBox(
width: MediaQuery.of(context).size.width * 0.95,
child: TextFormField(
controller: searchController,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: Icon(Icons.settings),
onPressed: () {
filterModalBottomSheet(context);
},
),
contentPadding: const EdgeInsets.only(),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(30),
),
),
onChanged: (value) {
setState(() {});
},
),
),
SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height * 0.8,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
itemCount: data.length,
itemBuilder: (context, index) {
return Card(
child: ListTile(
leading: Icon(Icons.person),
title: Text(data[index].nameSurname.toString()),
subtitle: Text(
"${data[index].city} / ${data[index].district}",
),
trailing: IconButton(
icon: const Icon(Icons.info),
onPressed: () {
Get.to(const NeedClothesPeopleDetailPage(),
arguments: data[index]);
print(data[index].nameSurname);
},
),
),
);
},
),
),
],
);
}
},
),
void filterModalBottomSheet(BuildContext context) {
showModalBottomSheet(
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(50),
topRight: Radius.circular(50),
),
),
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.5,
child: Padding(
padding: const EdgeInsets.only(left: 8, right: 8),
child: Column(
children: [
SizedBox(
height: MediaQuery.of(context).size.height * 0.04,
),
Row(
children: [
const Expanded(
flex: 1,
child: Text(
"İl:",
style: TextStyle(fontSize: 19),
),
),
Expanded(
flex: 9,
child: DropdownButtonFormField(
hint: const Text("İl seçiniz"),
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.location_city,
color: Color(0xFFCB3126),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: const BorderSide(
color: Color(0xFFCB3126),
),
),
),
items: citys
.map(
(e) => DropdownMenuItem<String>(
value: e.value,
child: e.child,
),
)
.toList(),
onChanged: (value) {
setState(() {
selectedCity = value.toString();
});
},
),
),
],
),
const SizedBox(height: 20),
Row(
children: [
const Expanded(
flex: 1,
child: Text(
"İlçe:",
style: TextStyle(fontSize: 19),
),
),
Expanded(
flex: 9,
child: DropdownButtonFormField(
key: getCityKey(),
hint: selectedCity == ""
? const Text("Önce il seçiniz")
: const Text("İlçe seçiniz"),
decoration: InputDecoration(
prefixIcon: const Icon(
Icons.location_city,
color: Color(0xFFCB3126),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(50),
borderSide: const BorderSide(
color: Color(0xFFCB3126),
),
),
),
items: districtsItem(),
onChanged: (value) {
setState(() {
selectedDistrict = value.toString();
});
},
),
),
],
),
const Spacer(),
Padding(
padding: const EdgeInsets.only(left: 12, right: 12),
child: SizedBox(
width: double.infinity,
height: 50,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFFCB3126),
),
child: const Text(
"Filtrele",
style: TextStyle(fontSize: 20),
),
onPressed: () {
setState(() {
filterActive = true;
Navigator.pop(context);
print(filterActive);
});
},
),
),
),
const SizedBox(height: 10),
],
),
),
);
},
);
},
);
}
The problem is this: When I call it by typing in TextFormField, the records in ListView.builder are changing. However, when filtering is done, the records do not change on the screen.
Why could this be? How can I solve the problem? Thanks.

Related

Alert Dialog not working as expected in flutter

I was trying to show 2 dialog same time and when i open second dialog, its not focusing on the widget that was in second dialog, its focusing on the widget thats on first dialog that i have opened before.
Is this issue or am i not supposed to open 2 dialog at same time?
Here is video to the issue
Here is first dialog code
showDialog(
context: context,
builder: (_) =>
AlertDialog(
title: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Row(
children: [
Container(
width: 16,
height: 32,
decoration: BoxDecoration(
color: AppColors.colorFFBC99,
borderRadius: BorderRadius.circular(4),
),
),
const SizedBox(
width: 16,
),
Text(
S.addaRecipe,
style: Theme.of(context).textTheme.headlineSmall!.copyWith(
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
],
),
SizedBox(
width: 300,
child: Row(
children: [
Text(
S.recipeBy,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontWeight: FontWeight.w500),
),
SizedBox(
width: 8,
),
Expanded(
child: CustomMyDropDownButton(label: 'dsfsdsf'),
),
],
),
)
],
),
content: Form(
// key: formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const SizedBox(
height: 16,
),
Text(
S.addPhotos,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontWeight: FontWeight.w500),
),
const SizedBox(
height: 8,
),
Container(
width: double.infinity,
// height: 200,
color: Colors.white,
child: Wrap(
children: [
for (int i = 0; i < 10; i++)
Padding(
padding: const EdgeInsets.all(8.0),
child: SizedBox(
width: 200,
height: 200,
child: ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.network(
S.recipeNetworkImage,
fit: BoxFit.cover,
),
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
onTap: () {},
child: Container(
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(8),
),
width: 200,
height: 200,
child: const Center(
child: Icon(
Icons.add,
size: 32,
),
),
),
),
),
],
),
),
const SizedBox(
height: 16,
),
CustomTextField(
showLabel: true,
// controller: textEditingController,
label: S.recipeName,
validator: (v) {
if (v!.isEmpty) {
return 'This field is required';
}
return null;
},
),
const SizedBox(
height: 16,
),
CustomTextField(
showLabel: true,
// controller: textEditingController,
label: S.description,
validator: (v) {
if (v!.isEmpty) {
return 'This field is required';
}
return null;
},
),
const SizedBox(
height: 32,
),
Row(
children: [
Text(
S.nutritionalInfo,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontWeight: FontWeight.w500),
),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text(
S.addNutrition,
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CustomTextField(
showLabel: true,
label: S.name,
),
CustomTextField(
showLabel: true,
label: S.value,
),
],
),
actions: [
CustomOutlinedButton(
name: S.close,
onPress: () {
context.pop();
}),
CustomElevatedButton(
name: S.add,
onPress: () {},
),
],
),
);
},
icon: const Icon(Icons.add),
)
],
),
const SizedBox(
height: 8,
),
Container(
padding: EdgeInsets.all(8),
color: Colors.grey.shade100,
child: 1 == 1
? Text(
"Nutrition Info....",
)
: Column(
children: [
for (int i = 0; i < 0; i++)
ListTile(
leading:
Icon(Icons.horizontal_split_rounded),
title: Text('Calories'),
subtitle: Text('237'),
trailing: IconButton(
onPressed: () {},
icon: Icon(Icons.delete),
),
),
],
),
),
const SizedBox(
height: 32,
),
Text(
S.steps,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontWeight: FontWeight.w500),
),
const SizedBox(
height: 8,
),
Container(
color: AppColors.colorF4F4F4,
height: 300,
width: MediaQuery.of(context).size.width * .8,
child: HtmlEditor(
controller: HtmlEditorController(),
htmlEditorOptions: const HtmlEditorOptions(
hint: "Steps....",
),
otherOptions: const OtherOptions(
height: 400,
decoration: BoxDecoration(color: Colors.red)),
),
),
const SizedBox(
height: 32,
),
],
),
),
),
const SizedBox(
height: 32,
),
Stack(
children: [
Text(
'',
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Colors.red,
),
),
Text(
'',
maxLines: 3,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodyMedium!.copyWith(
color: Colors.green,
),
),
],
),
],
),
),
actions: [
CustomOutlinedButton(
name: S.close,
onPress: () {
context.pop();
}),
CustomElevatedButton(
name: S.add,
onPress: () {},
),
],
);
Here is the code of second dialog show dialog
showDialog(
context: context,
builder: (_) => AlertDialog(
title: const Text(
S.addNutrition,
),
content: Column(
mainAxisSize: MainAxisSize.min,
children: const [
CustomTextField(
showLabel: true,
label: S.name,
),
CustomTextField(
showLabel: true,
label: S.value,
),
],
),
actions: [
CustomOutlinedButton(
name: S.close,
onPress: () {
context.pop();
}),
CustomElevatedButton(
name: S.add,
onPress: () {},
),
],
),
);
Here is customtextfield code
import 'package:flutter/material.dart';
class CustomTextField extends StatefulWidget {
final String? label;
final TextEditingController? controller;
final String? Function(String?)? validator;
final Function(String?)? onSaved;
final bool showLabel;
final bool enableSuggestions;
final bool autocorrect;
final TextInputType? keyBoardType;
final Function(String)? onChange;
final bool showSuffixIcon;
const CustomTextField({
Key? key,
this.label,
this.controller,
this.validator,
this.onSaved,
this.enableSuggestions = true,
this.autocorrect = true,
this.keyBoardType,
this.onChange,
this.showSuffixIcon = false,
this.showLabel = false,
}) : super(key: key);
#override
State<CustomTextField> createState() => _CustomTextFieldState();
}
class _CustomTextFieldState extends State<CustomTextField> {
final textFieldFocusNode = FocusNode();
bool _obscured = false;
#override
void initState() {
// TODO: implement initState
if (widget.showSuffixIcon) {
_obscured = true;
}
super.initState();
}
void _toggleObscured() {
setState(() {
_obscured = !_obscured;
if (textFieldFocusNode.hasPrimaryFocus)
return; // If focus is on text field, dont unfocus
textFieldFocusNode.canRequestFocus =
false; // Prevents focus if tap on eye
});
}
#override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
widget.showLabel
? Text(
widget.label!,
style: Theme.of(context)
.textTheme
.labelLarge!
.copyWith(fontWeight: FontWeight.w500),
)
: const SizedBox(),
SizedBox(
height: widget.showLabel ? 8 : 0,
),
TextFormField(
controller: widget.controller,
validator: widget.validator,
onSaved: widget.onSaved,
onChanged: widget.onChange,
focusNode: textFieldFocusNode,
obscureText: _obscured,
enableSuggestions: widget.enableSuggestions,
autocorrect: widget.autocorrect,
keyboardType: widget.keyBoardType,
decoration: InputDecoration(
isDense: true,
enabledBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
borderSide: BorderSide(
color: Colors.black12,
),
),
focusedBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
borderSide: BorderSide(
color: Colors.black12,
),
),
errorBorder: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
borderSide: BorderSide(
color: Colors.red,
),
),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(8),
),
borderSide: BorderSide(
color: Colors.black12,
),
),
labelText: widget.showLabel ? null : widget.label,
// labelStyle: CustomTextStyle.kTextStyle16400.copyWith(
// color: AppColors.textColor2,
// ),
suffixIcon: widget.showSuffixIcon
? Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 4, 0),
child: GestureDetector(
onTap: _toggleObscured,
child: Icon(
_obscured
? Icons.visibility_rounded
: Icons.visibility_off_rounded,
size: 24,
color: Colors.grey,
),
),
)
: null,
),
),
],
);
}
}
Try to add autofocus: true, on your CustomTextField. It should do handle rest I believe.
TextField(
autofocus: true,
);

flutter A RenderFlex overflowed by 271 pixels on the bottom

Hello I am using SingleChildScrollView and I am getting this error 'A RenderFlex is overflowing with 271 pixels at the bottom'. I think it's because you're using the appBar's PreferredSize and tabBarview. Sorry for the long code.
A widget that uses a abbar tabbarView.
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
appBar: PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: Container(
color: Colors.black,
child: SafeArea(
child: Column(
children: [
TabBar(
indicatorColor: Colors.grey,
controller: this._tabController,
tabs: [
Tab(
text: 'MOVIE',
),
Tab(
text: 'TV',
),
],
),
],
)),
),
),
// bottom:
body: TabBarView(
controller: this._tabController,
children: [
Column(
children: [
search(),
this.movieName.isNotEmpty ? searchMovieTile() : Container(),
],
),
Column(
children: [
search(),
this.movieName.isNotEmpty ? searchTvTile() : Container(),
],
)
],
),
);
}
A widget that uses a SingleChildScrollView.
Widget searchMovieTile() {
return FutureBuilder(
future: this._searchController.searchMovie(movieName: this.movieName),
builder:
(BuildContext context, AsyncSnapshot<List<SearchModel>> snapshot) {
if (snapshot.hasData) {
return Consumer<SearchProvider>(
builder: (context, value, child) {
return snapshot.data!.isEmpty
? Container()
: SingleChildScrollView(
child: Container(
height: MediaQuery.of(context).size.height,
child: GridView.count(
childAspectRatio: 2 / 3,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
crossAxisCount: 3,
children: List.generate(
snapshot.data!.length,
(index) => ClipRRect(
borderRadius: BorderRadius.circular(15.0),
child: snapshot.data![index].posterPath.isEmpty
? Container(
child: Center(
child: Text(
'Image preparation',
style: TextStyle(color: Colors.white),
),
),
)
: GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(builder:
(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(
create: (BuildContext
context) =>
MovieDetailProvider()),
ChangeNotifierProvider(
create:
(BuildContext context) =>
MovieVideoProvider()),
],
child: SearchMovieDetailScreen(
movieData:
snapshot.data![index]),
);
}));
},
child: CachedNetworkImage(
fit: BoxFit.cover,
imageUrl:
'https://image.tmdb.org/t/p/original/${snapshot.data![index].posterPath}',
),
),
),
),
),
),
);
},
);
} else {
return Container();
}
},
);
}
A widget that uses a textfield keyboard.
Widget search() {
return Container(
padding: EdgeInsets.only(
left: 5.0,
top: 10.0,
right: 5.0,
bottom: 10.0,
),
child: Row(
children: [
Expanded(
flex: 6,
child: TextField(
onSubmitted: (String name) {
this.movieName = this._textEditingController.text;
print(this.movieName);
},
cursorColor: Colors.grey,
focusNode: this._focusNode,
style: TextStyle(
color: Colors.white,
fontSize: 15.0,
),
controller: this._textEditingController,
decoration: InputDecoration(
filled: true,
fillColor: Colors.grey[900],
prefixIcon: Icon(
Icons.search,
color: Colors.grey,
size: 20.0,
),
suffixIcon: this._focusNode.hasFocus
? IconButton(
onPressed: () {
setState(() {
this._textEditingController.clear();
});
},
icon: Icon(
Icons.cancel,
size: 20.0,
color: Colors.grey,
),
)
: Container(),
hintText: 'Search',
hintStyle: TextStyle(color: Colors.grey),
labelStyle: TextStyle(color: Colors.white),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
borderRadius: BorderRadius.circular(10.0),
),
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
borderRadius: BorderRadius.circular(10.0),
),
border: OutlineInputBorder(
borderSide: BorderSide(
color: Colors.transparent,
),
borderRadius: BorderRadius.circular(10.0),
),
),
),
),
this._focusNode.hasFocus
? Expanded(
child: TextButton(
child: Text(
'cancel',
style: TextStyle(
fontSize: 13.0,
color: Colors.grey,
),
),
onPressed: () {
setState(() {
this._textEditingController.clear();
this._focusNode.unfocus();
});
},
))
: Expanded(flex: 0, child: Container())
],
),
);
}
Sorry for the low level of the question, but I'd appreciate it if you could answer :)
I think this problem is due to the given height to the container (child of SingleChildScrollView:
SingleChildScrollView(
child: Container(
**height: MediaQuery.of(context).size.height,**
child: GridView.count(
just remove it and let me know the result.
try : height: MediaQuery.of(context).size.height - 280,

How to have the text from a selected item inside a text field in flutter

I have an edit function which displays in a dialog in my to do list app on flutter. When an item is selected to be edited, a dialog containing a TextField(to enter the new value of the selected item) and a button(to save the changes) appears. The goal is to have the text of the selected item on the TextField of the dialog, currently my code has a hintText inside the TextField that does display the value of the selected item but what I want to achieve is to have that in the controller.
If you didnt understood what I want to achieve see this edit function like instagram's one, when editing a post on instagram you don't have to type everything again instead when editing you have the original text of the post there. Well that is not happening on my app, when editing an item the TextField doesnt show anything. How can I make this work?
code related to the edit function
List<ToDoElement> _toDoItems = [];
TextEditingController _editController = TextEditingController();
void _editToDoItem(String newText, int index) {
setState(() {
_toDoItems[index].task = newText;
});
}
_editDialog(BuildContext context, int index) {
return showDialog(context: context, builder: (context){
return Dialog(
backgroundColor: Colors.transparent,
insetAnimationDuration:
const Duration(milliseconds: 800),
child: Container(
padding: EdgeInsets.all(20),
height: 180,
width: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 60,
child: TextField( // this is the textfield that I should have the text of the selected item inside.
controller: _editController,
autofocus: true,
autocorrect: false,
onSubmitted: (val) {
FocusScope.of(context).requestFocus(FocusNode());
_editToDoItem(val, index);
Navigator.of(context).pop();
},
decoration: InputDecoration(
hintText: '${_toDoItems[index].task}', //this hint text shows the value of the selected item, yhis is what I want to have but in the controller.
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
)
),
Container(
height: 65,
width: double.infinity,
margin: EdgeInsets.only(top: 5,),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('EDIT', style: TextStyle(fontSize: 18)),
onPressed: () {
_editToDoItem(_editController.text, index);
FocusScope.of(context).requestFocus(FocusNode());
Navigator.of(context).pop();
},
),
),
],
),
),
);
});
}
full main.dart
import 'package:flutter/material.dart';
class ToDoElement {
String task;
final DateTime timeOfCreation;
ToDoElement(this.task, this.timeOfCreation);
}
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
#override
createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
List<ToDoElement> _toDoItems = [];
TextEditingController _controller = TextEditingController();
TextEditingController _editController = TextEditingController();
void _addToDoItem(String task) {
if(task.isNotEmpty) {
setState(() {
_toDoItems.add(ToDoElement(task, DateTime.now()));
});
}
}
void _editToDoItem(String newText, int index) {
setState(() {
_toDoItems[index].task = newText;
});
}
void _removeTodoItem(int index) {
setState(() => _toDoItems.removeAt(index));
}
_editDialog(BuildContext context, int index) {
return showDialog(context: context, builder: (context){
return Dialog(
backgroundColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)
),
insetAnimationDuration:
const Duration(milliseconds: 800),
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
padding: EdgeInsets.all(20),
height: 180,
width: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 60,
child: TextField(
controller: _editController,
autofocus: true,
autocorrect: false,
onSubmitted: (val) {
FocusScope.of(context).requestFocus(FocusNode());
_editToDoItem(val, index);
Navigator.of(context).pop();
},
style: TextStyle(fontSize: 17,),
decoration: InputDecoration(
hintText: '${_toDoItems[index].task}',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
)
),
Container(
height: 65,
width: double.infinity,
margin: EdgeInsets.only(top: 5,),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('EDIT', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_editToDoItem(_editController.text, index);
FocusScope.of(context).requestFocus(FocusNode());
Navigator.of(context).pop();
},
),
),
],
),
),
);
});
}
Widget _buildToDoItem(String toDoText, int index) {
return SizedBox(
child: Container(
height: 58,
margin: EdgeInsets.only(left: 22.0, right: 22.0, bottom: 12,),
decoration: BoxDecoration(
border: Border.all(width: 1.5, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(18)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children:[
Expanded(
child: ListTile(
title: Text(
toDoText,
style: TextStyle(fontSize: 18),
),
onTap: () => null,
),
),
FlatButton(
child: Text('Edit', style: TextStyle(color: Colors.red, fontSize: 16.5),),
onPressed: () => _editDialog(context, index),
),
FlatButton(
child: Text('Delete', style: TextStyle(color: Colors.red, fontSize: 16.5),),
onPressed: () => _removeTodoItem(index),
),
],
),
),
);
}
int compareElement(ToDoElement a, ToDoElement b) =>
a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;
Widget _buildToDoList() {
_toDoItems.sort(compareElement);
return Expanded(
child: ListView.builder(
itemCount: _toDoItems.length,
itemBuilder: (context, index) {
if (index < _toDoItems.length) {
return _buildToDoItem(_toDoItems[index].task, index);
}
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
centerTitle: true,
backgroundColor: Colors.red,
title: Text('To Do List', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold,),),
)
),
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 60,
margin: EdgeInsets.all(22),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 10,
child: Container(
height: double.infinity,
child: TextField(
controller: _controller,
autofocus: true,
onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},
style: TextStyle(fontSize: 18,),
decoration: InputDecoration(
hintText: 'Add a task here...',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
),
),
),
Expanded(
flex: 4,
child: Container(
height: double.infinity,
margin: EdgeInsets.only(left: 12),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('ADD', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_addToDoItem(_controller.text);
_controller.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
),
],
),
),
_buildToDoList()
]
),
),
);
}
}
If you have any questions please let me know in the comments;)
You already have the _editController variable. You can use it not only to get the typed text but also to set it:
You can do it before calling the edit function, for example:
[...]
onPressed: () {
_editController.text = toDoText;
_editDialog(context, index);
},
[...]
(Or maybe before creating the dialog, if you prefer.)
As you can see in the documentation:
A TextEditingController can also be used to provide an initial value for a text field. If you build a text field with a controller that already has text, the text field will use that text as its initial value.

How to edit a selected item from a list in flutter

I have been trying to add an edit function to my to do list in which a user can select the item the user wants to edit, then that should pop a dialog where there is a textfield to enter the new value of the selected item and a Button that saves the changes. Currently I have a function that calls the array where the tasks are stored then it is supposed to triger the selected item using index so that at the end that selected value could be given a new value when onPressed, see this edit functionality as instagrams one except it edits text.
The problem comes when calling that function into the dialog's edit button because I am doing it like this onPressed: () => _editToDoItem(_controller.text, index) and since I have to pass 2 parameters there, the error I am getting is Undefined name 'index'. How can this problem be solved to make this edit function work?. By the way, I haven't get to try the edit function because of this error so please correct me if the function or any part of the code is incorrect.
everything to do with the edit function below.
List<ToDoElement> _toDoItems = [];
TextEditingController _controller = TextEditingController();
// this function adds a task to the list
void _addToDoItem(String task) {
if(task.isNotEmpty) {
setState(() {
_toDoItems.add(ToDoElement(task, DateTime.now()));
});
}
}
// this is the function that is supposed to edit the selected index from the _toDoItems array
void _editToDoItem(String newText, int index) {
setState(() {
_toDoItems[index].task = newText;
});
}
_editDialog(BuildContext context) {
return showDialog(context: context, builder: (context) {
return Dialog(
child: Container(
height: 180,
width: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 60,
child: TextField(
controller: _controller,
autofocus: true,
style: TextStyle(fontSize: 18,),
)
),
Container(
height: 65,
width: double.infinity,
margin: EdgeInsets.only(top: 5,),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('EDIT'),
onPressed: () {
_editToDoItem(_controller.text, index); // error on index, Undefined name 'index'
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
],
),
),
);
});
}
full main.dart file
class ToDoElement {
String task;
final DateTime timeOfCreation;
ToDoElement(this.task, this.timeOfCreation);
}
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
#override
createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
List<ToDoElement> _toDoItems = [];
TextEditingController _controller = TextEditingController();
void _addToDoItem(String task) {
if(task.isNotEmpty) {
setState(() {
_toDoItems.add(ToDoElement(task, DateTime.now()));
});
}
}
void _editToDoItem(String newText, int index) {
setState(() {
_toDoItems[index].task = newText;
});
}
void _removeTodoItem(int index) {
setState(() => _toDoItems.removeAt(index));
}
_editDialog(BuildContext context) {
return showDialog(context: context, builder: (context) {
return Dialog(
backgroundColor: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
padding: EdgeInsets.all(20),
height: 180,
width: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 60,
child: TextField(
controller: _controller,
autofocus: true,
/*onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},*/
style: TextStyle(fontSize: 18,),
decoration: InputDecoration(
hintText: 'Add a task here...',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
)
),
Container(
height: 65,
width: double.infinity,
margin: EdgeInsets.only(top: 5,),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('EDIT', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_editToDoItem(_controller.text, index);
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
],
),
),
);
});
}
Widget _buildToDoItem(String toDoText, int index) {
return SizedBox(
child: Container(
height: 58,
margin: EdgeInsets.only(left: 22.0, right: 22.0, bottom: 12,),
decoration: BoxDecoration(
border: Border.all(width: 1.5, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(18)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children:[
Expanded(
child: ListTile(
title: Text(
toDoText,
style: TextStyle(fontSize: 18),
),
onTap: () => null,
),
),
FlatButton(
child: Text('Edit', style: TextStyle(color: Colors.red, fontSize: 16.5),),
onPressed: () => _editDialog(context),
),
FlatButton(
child: Text('Delete', style: TextStyle(color: Colors.red, fontSize: 16.5),),
onPressed: () => _removeTodoItem(index),
),
],
),
),
);
}
int compareElement(ToDoElement a, ToDoElement b) =>
a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;
Widget _buildToDoList() {
_toDoItems.sort(compareElement);
return Expanded(
child: ListView.builder(
itemCount: _toDoItems.length,
itemBuilder: (context, index) {
if (index < _toDoItems.length) {
return _buildToDoItem(_toDoItems[index].task, index);
}
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
centerTitle: true,
backgroundColor: Colors.red,
title: Text('To Do List', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold,),),
)
),
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 60,
margin: EdgeInsets.all(22),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 10,
child: Container(
height: double.infinity,
child: TextField(
controller: _controller,
autofocus: true,
onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},
style: TextStyle(fontSize: 18,),
decoration: InputDecoration(
hintText: 'Add a task here...',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
),
),
),
Expanded(
flex: 4,
child: Container(
height: double.infinity,
margin: EdgeInsets.only(left: 12),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('ADD', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_addToDoItem(_controller.text);
_controller.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
),
],
),
),
_buildToDoList()
]
),
),
);
}
}
If you have any questions please let me know in the comments;)
You can copy paste run full code below
You can provide index to _editDialog then _editToDoItem can get index
code snippet
_editDialog(BuildContext context, int index)
...
FlatButton(
child: Text(
'Edit',
style: TextStyle(color: Colors.red, fontSize: 16.5),
),
onPressed: () => _editDialog(context, index),
),
working demo
full code
import 'package:flutter/material.dart';
class ToDoElement {
String task;
final DateTime timeOfCreation;
ToDoElement(this.task, this.timeOfCreation);
}
void main() => runApp(MaterialApp(home: MyApp()));
class MyApp extends StatefulWidget {
#override
createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
List<ToDoElement> _toDoItems = [];
TextEditingController _controller = TextEditingController();
TextEditingController _controller1 = TextEditingController();
void _addToDoItem(String task) {
if (task.isNotEmpty) {
setState(() {
_toDoItems.add(ToDoElement(task, DateTime.now()));
});
}
}
void _editToDoItem(String newText, int index) {
setState(() {
_toDoItems[index].task = newText;
});
}
void _removeTodoItem(int index) {
setState(() => _toDoItems.removeAt(index));
}
_editDialog(BuildContext context, int index) {
return showDialog(
context: context,
builder: (context) {
return Dialog(
backgroundColor: Colors.transparent,
child: Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(20.0)),
),
padding: EdgeInsets.all(20),
height: 180,
width: 100,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 60,
child: TextField(
controller: _controller,
autofocus: true,
/*onSubmitted: (val) {
_addToDoItem(val);
_controller.clear();
},*/
style: TextStyle(
fontSize: 18,
),
decoration: InputDecoration(
hintText: 'Add a task here...',
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
)),
Container(
height: 65,
width: double.infinity,
margin: EdgeInsets.only(
top: 5,
),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('EDIT', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_editToDoItem(_controller.text, index);
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
],
),
),
);
});
}
Widget _buildToDoItem(String toDoText, int index) {
return SizedBox(
child: Container(
height: 58,
margin: EdgeInsets.only(
left: 22.0,
right: 22.0,
bottom: 12,
),
decoration: BoxDecoration(
border: Border.all(width: 1.5, color: Colors.red),
borderRadius: BorderRadius.all(Radius.circular(18)),
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: ListTile(
title: Text(
toDoText,
style: TextStyle(fontSize: 18),
),
onTap: () => null,
),
),
FlatButton(
child: Text(
'Edit',
style: TextStyle(color: Colors.red, fontSize: 16.5),
),
onPressed: () => _editDialog(context, index),
),
FlatButton(
child: Text(
'Delete',
style: TextStyle(color: Colors.red, fontSize: 16.5),
),
onPressed: () => _removeTodoItem(index),
),
],
),
),
);
}
int compareElement(ToDoElement a, ToDoElement b) =>
a.timeOfCreation.isAfter(b.timeOfCreation) ? -1 : 1;
Widget _buildToDoList() {
_toDoItems.sort(compareElement);
return Expanded(
child: ListView.builder(
itemCount: _toDoItems.length,
itemBuilder: (context, index) {
if (index < _toDoItems.length) {
return _buildToDoItem(_toDoItems[index].task, index);
}
},
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50),
child: AppBar(
centerTitle: true,
backgroundColor: Colors.red,
title: Text(
'To Do List',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
)),
backgroundColor: Colors.white,
body: GestureDetector(
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Column(crossAxisAlignment: CrossAxisAlignment.center, children: [
Container(
height: 60,
margin: EdgeInsets.all(22),
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
flex: 10,
child: Container(
height: double.infinity,
child: TextField(
controller: _controller1,
autofocus: true,
onSubmitted: (val) {
_addToDoItem(val);
_controller1.clear();
},
style: TextStyle(
fontSize: 18,
),
decoration: InputDecoration(
hintText: 'Add a task here...',
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
borderSide: BorderSide(color: Colors.red, width: 2),
),
),
),
),
),
Expanded(
flex: 4,
child: Container(
height: double.infinity,
margin: EdgeInsets.only(left: 12),
child: RaisedButton(
textColor: Colors.white,
color: Colors.red,
child: Text('ADD', style: TextStyle(fontSize: 18)),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12)),
),
onPressed: () {
_addToDoItem(_controller1.text);
_controller1.clear();
FocusScope.of(context).requestFocus(FocusNode());
},
),
),
),
],
),
),
_buildToDoList()
]),
),
);
}
}

How to use setstate in the Void function?

I'm still new to Flutter. I want to ask why I can't use setState () in void function
here's my code: my goal is that the slider can be responsive. Previous problem I am still confused in using the SetState void function. so first of all when pressing the filter button a pop up window will appear where will display the contents of the filter that is several categories, then in the price category there is a function to display the slider. and my slider is like just an image and can't be changed. but the value has changed
void _onButtonPressed1() {
//Function for Button Press "Sort"
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
color: Colors.black,
height: 500,
child: Container(
child: column1(),
decoration: BoxDecoration(
color: Colors.cyan[400],
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(30),
topRight: const Radius.circular(30),
)),
),
);
});}
new Expanded(
child: new Padding(
//padding overall filter include text&square
padding: EdgeInsets.fromLTRB(15, 0, 20, 0),
child: new Card(
color: Colors.transparent,
shape: const RoundedRectangleBorder(
side: BorderSide(
color: Colors.cyanAccent,
),
borderRadius: BorderRadius.all(Radius.circular(6.0)),
),
child: new RaisedButton(
child: new Row(children: <Widget>[
new Padding(
padding: EdgeInsets.fromLTRB(5.0, 0, 40, 0),
child: new Icon(Icons.format_align_left, color: Colors.cyanAccent),
),
new Text(
'Filter',
style: new TextStyle(
fontSize: 13,
color: Colors.cyanAccent,
),
),
]),
color: Colors.black,
padding: EdgeInsets.fromLTRB(1, 1, 1, 1),
onPressed: () => {
showModalBottomSheet(
context: context,
builder: (context) {
return Container(
color: Colors.black,
height: 350,
child: Container(
// child: column(),
child: Wrap(
//dropdown button
children: <Widget>[
ListView.builder(
shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
if (index < 2) {
final sort = _sort[index];
return ExpansionTile(
title: ListTile(
title: Text(
sort.category,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
children: <Widget>[ListTile(title: sort.item)],
);
} else {
return ExpansionTile(
title: ListTile(
title: Text(
'By Price',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)),
children: <Widget>[
new RangeSlider(
min: 1,
max: 100,
divisions: 100,
values: values,
labels: labels,
onChanged: (value) {
print('START: ${value.start}, END: ${value.end}');
values = value;
labels = RangeLabels('${values.start.toInt().toString()}\$', '${values.end.toInt().toString()}\$');
setState(() {});
},
//Data from API
)
]);
}
}),
],
),
decoration: BoxDecoration(
color: Colors.cyan[400],
borderRadius: BorderRadius.only(
topLeft: const Radius.circular(30),
topRight: const Radius.circular(30),
)),
),
);
},
)
}),
),
),
),
onPressed: () => {
showModalBottomSheet(
context: context,
builder: (_) =>
StatefulBuilder(builder:(modalContext, modalSetState) => Container(
color: Colors.black,
height: 350,
child: Container(
height:200,
// child: column(),
child: Wrap(
//dropdown button
children: <Widget>[
new Text(values.start.toString()),
ListView.builder(
shrinkWrap: true,
itemCount: 3,
itemBuilder: (context, index) {
context=context;
if (index < 2) {
final sort = _sort[index];
return ExpansionTile(
title: ListTile(
title: Text(
sort.category,
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
),
),
children: <Widget>[ListTile(title: sort.item)],
);
} else {
return ExpansionTile(
title: ListTile(
title: Text(
'By Price',
style: TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)),
children: <Widget>[
new RangeSlider(
min: 1,
max: 100,
divisions: 100,
values: values,
labels: labels,
onChanged: (value) {
print('START: ${value.start}, END: ${value.end}');
setValuesSlider(value);
labels = RangeLabels('${values.start.toInt().toString()}\$', '${values.end.toInt().toString()}\$');
modalSetState(() {});
},
//Data from API
)
]);
}
}),
],
...
Just use StatefulBuilder(builder:(modalContext, modalSetState)