I want to convert this ListView into ListView.builder, but somehow I could not figure out how I could do it. Any help would be greatly appreciated.
ListView(
children: snapshot.data!.docs.map((doc) {
final dynamic data = doc.data();
return Visibility(
child:
ContactListTileField(
text: data['contactName'].toString(),
iconData: Icons.delete,
function: () async {
DialogBox.dialogBox(
"Do you really want to delete ${data['contactName'].toString().capitalize}? "
, context
, (){
deleteContact(,context);
});
})
);
}).toList(),
)
ListView.builder(
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
final doc = snapshot.data!.docs[index];
final dynamic data = doc.data();
return Visibility(
child: ContactListTileField(
text: data['contactName'].toString(),
iconData: Icons.delete,
function: () async {
DialogBox.dialogBox(
"Do you really want to delete ${data['contactName'].toString().capitalize}? "
, context
, (){
deleteContact(,context);
});
})
);}
)
Try this...
Related
Hi in my flutter app have FutureBuilder that return listview, my list listview create some button for update the hive table. when I click the first time on one of buttons everything is run smoothly, but when I click on same button again my hive key turn to null and program show my this error: "type 'Null' is not a subtype of type 'int' "
I write print all over my code but still I do not get it why the key turn null from the second time.
How can I Correct this? please help my.
my Futurebuilder body is:
FutureBuilder<List>(
future: controller.showTaskList(),
builder: (context, snapshot) {
switch (snapshot.connectionState) {
case ConnectionState.waiting:
return SizedBox(
height: Get.height,
child: const Center(
child: CircularProgressIndicator(),
),
);
default:
if (snapshot.hasError) {
return Text('Error: ${snapshot.error}');
} else {
List data = snapshot.data ?? [];
return ListView.separated(
scrollDirection: Axis.vertical,
physics:
const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (context, index) {
// controller.taskIconCheckList
// .clear();
for (int i = 0;
i < data.length;
i++) {
if (data[i].status == true) {
controller.taskIconCheckList
.add(true.obs);
} else {
controller.taskIconCheckList
.add(false.obs);
}
}
return ListTile(
leading: Obx(
() => PageTransitionSwitcher(
transitionBuilder: (
child,
primaryAnimation,
secondaryAnimation,
) {
return SharedAxisTransition(
animation:
primaryAnimation,
secondaryAnimation:
secondaryAnimation,
transitionType:
SharedAxisTransitionType
.horizontal,
fillColor:
Colors.transparent,
child: child,
);
},
duration: const Duration(
milliseconds: 800),
child: controller
.taskIconCheckList[
index]
.value
? SizedBox(
child: IconButton(
icon: const Icon(
Icons
.check_circle_rounded,
color: Colors
.lightGreenAccent,
),
onPressed: () {
controller
.functionTaskIconCheckList(
index,
);
print('طول دیتا');
print(data.length.toString());
print('مقدار ایندکس');
print(index.toString());
print('مقدار کلید');
print(data[index].key.toString());
print(data[index].taskText.toString());
controller
.updateStatusTask(
index,
data[index]
.key); // here when i first click // return key currectly, but after that show null and updatestatusetask not run and show error.
},
),
)
: IconButton(
onPressed: () {
controller
.functionTaskIconCheckList(
index,
);
print('طول دیتا');
print(data.length.toString());
print('مقدار ایندکس');
print(index.toString());
print('مقدار کلید');
print(data[index].key.toString());
print(data[index].taskText.toString());
controller
.updateStatusTask(
index,
data[index]
.key); // here when i first click // return key currectly, but after that show null and updatestatusetask not run and show error.
},
icon: const Icon(
Icons
.radio_button_unchecked_outlined,
color: Colors.red,
),
),
),
),
title: Text(data[index].taskText,
style: normalTextForCategory),
subtitle: Text(
data[index]
.date
.toString()
.substring(0, 10),
textDirection:
TextDirection.ltr,
textAlign: TextAlign.right,
style: normalTextForSubtitle,
),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: () {
myDefaultDialog(
'هشدار',
'آیا از حذف این گزینه اطمینان دارید؟',
'بله',
'خیر',
() {
Get.back();
mySnakeBar(
'',
'گزینه مورد نظر با موفقیت حذف شد.',
Icons
.warning_amber_rounded,
Colors.yellow);
},
);
},
icon: const Icon(
Icons.delete),
color: Colors.redAccent,
),
IconButton(
onPressed: () {
Get.offNamed(
Routs.editTaskScreen,
arguments: 'edit');
},
icon: const Icon(
Icons.edit_calendar,
color:
Colors.yellowAccent,
),
),
],
),
);
},
separatorBuilder:
(BuildContext context,
int index) {
return const Divider(
height: 2,
color: Colors.white70,
);
},
);
}
}
},
),
this is my functionTaskIconCheckList form controller:
functionTaskIconCheckList(int index) {
taskIconCheckList[index].value = !taskIconCheckList[index].value;}
and this the updatestatusetask function
updateStatusTask(int index,int taskKey) async {
print('در تابع آپدیت ایندکس هست: ${index.toString()}');
print('در تابع آپدیت کی هست: ${taskKey.toString()}');
var taskBox = await Hive.openBox('task');
var filterTask = taskBox.values.where((task) => task.key == taskKey).toList();
Task task = Task(
filterTask[0].taskText,
filterTask[0].date,
taskIconCheckList[index].value,
filterTask[0].deleteStatus,
null,
null,
filterTask[0].taskCatId,
filterTask[0].userId);
await taskBox.put(taskKey, task);}
and this is my showtasklist function:
Future<List> showTaskList() async {
SharedPreferences sharedPreferences = await SharedPreferences.getInstance();
var taskBox = await Hive.openBox('task');
var filterTask = taskBox.values
.where((task) => task.userId == sharedPreferences.getInt('key'))
.toList();
return filterTask;}
this is my model:
#HiveType(typeId: 2)
class Task extends HiveObject{
#HiveField(0)
String taskText;
#HiveField(1)
DateTime date;
#HiveField(2)
bool status;
#HiveField(3)
bool deleteStatus;
#HiveField(4)
int taskCatId;
#HiveField(5)
int userId;
#HiveField(6)
User? user;
#HiveField(7)
TaskCat? taskCat;
Task(this.taskText, this.date, this.status, this.deleteStatus, this.user,
this.taskCat, this.taskCatId, this.userId);
}
One possible solution would be to wait for the Future function to finish and then load the list. If it tries to load the list early before finishing up the Future function, it might presume the value to be null.
Hope this helps.
Still I do not know what is cause this problem, But I found an alternative temporary solution. I create temporary Int list. then just before the return listTile in the futureBuilder body, I write the Loop and save all of the key in that list. finally instead of pass the "data[index].key." I pass my key from that temporary Int list. so everything work fine now
this is my part of code change from before, but still I want know main solution.
return ListView.separated(
scrollDirection: Axis.vertical,
physics:
const BouncingScrollPhysics(),
shrinkWrap: true,
itemCount: data.length,
itemBuilder: (context, index) {
// controller.taskIconCheckList
// .clear();
for (int i = 0;
i < data.length;
i++) {
Get.find<
HomeScreenController>()
.taskKey.add(data[i].key);
if (data[i].status == true) {
Get.find<
HomeScreenController>()
.taskIconCheckList
.add(true.obs);
} else {
Get.find<
HomeScreenController>()
.taskIconCheckList
.add(false.obs);
}
}
return ListTile(
i am getting values from server to dropdown which are inserted previous from static list of dropdown values, but i need to use dropdown when value from server is 'Pending' to update specific record, below my code.
List<String> approvalList = ['Pending', 'Approve', 'Discard'];
String dropdownValue="Pending";
Container(
height: MediaQuery.of(context).size.height*0.3,
width: MediaQuery.of(context).size.width,
child:StreamBuilder<List<ApprovalModel>>(
stream: bloc.approvalsStream,
initialData: [],
builder: (context, snapshot) {
return ListView.builder(
itemCount: snapshot.data!.length,
itemBuilder: (context,i){
return snapshot.connectionState==ConnectionState.waiting?Lottie.asset(
'assets/lottieloading.json',
width: 70,
height: 70,
fit: BoxFit.fill,
):ListTile(
title: Text(snapshot.data![i].approverName),
trailing: StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return DropdownButton<String>(
value: snapshot.data![i].status==0?'Pending':
snapshot.data![i].status==1?'Approve':
'Discard',
items: approvalList.map((String val) {
return DropdownMenuItem<String>(
value: val,
child: new Text(val),
);
}).toList(),
hint: Text(selectedValue),
onChanged: (val) {
setState(() {
dropdownValue = val!;
});
});
}
),
);
});
}
)
,
),
As You see i am setting value from server it is working fine, but when the value is pending i want to use the dropdown to update record in database.
At onChanged when you update your dropdownValue , also call the method you are using to update record in database.
I'm new with Flutter. Currently I am trying to do the CRUD. But then I got some error to delete the data by ID. I did manage to do the delete operation but then it will delete the latest inserted data instead, not the data that onTap. Here I attach my source code.
String docId;
#override
Widget build(BuildContext context) {
CollectionReference users = FirebaseFirestore.instance.collection('taks');
DocumentSnapshot ds;
return new StreamBuilder(
stream: users.snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return new Text('Loading...');
return new ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
ds = snapshot.data.docs[index];
// children: snapshot.data.docs.map((document) {
return new ListTile(
title: new Text(ds['task']),
subtitle: Wrap(
children: <Widget>[
Text("Priority: " + ds['priority']),
Text(" | Status: " + ds['status']),
],
),
onTap: (){
docId = ds.id;
print(docId);
},
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
IconButton(
icon: Icon(
Icons.update_rounded,
size: 20.0,
color: Colors.brown[900],
),
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => UpdateScreen(docId)));
}
),
IconButton(
icon: Icon(
Icons.delete_outline,
size: 20.0,
color: Colors.brown[900],
),
onPressed: () async {
try {
FirebaseFirestore.instance
.collection("taks")
.doc(docId)
.delete()
.then((_) {
print("success!");
});
}
catch (e) {
print("ERROR DURING DELETE");
}
// _onDeleteItemPressed(index);
},
),
],
),
// subtitle: new Text(document['priority']),
);
});
// );
},
);
So, I tried to print the docId on which row that been selected. I tap all the data but it will only read the latest data id only.
So can anyone help me to sort out this problem on how to delete the data that been selected only, not always delete the latest data? Thank you in advanced
I'm sure I understand what exactly it is you want to delete, but your function tells Firebase to delete the entire document with the ID you are passing.
You also are defining `String docId' to your whole widget and using it for all your ListView.Builder items.
Try this:
ListView.builder(
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
ds = snapshot.data.docs[index];
String docIdTobeDeleted= ds.id;
// children: snapshot.data.docs.map((document) {
return new ListTile(
title: new Text(ds['task']),
subtitle: Wrap(
children: <Widget>[
Text("Priority: " + ds['priority']),
Text(" | Status: " + ds['status']),
],
),
onTap: (){
//you won't be needing this anymore, instead you can type:
print(docIdTobeDeleted);
//docId = ds.id;
//print(docId);
},
and for firebase below, use this:
onPressed: () async {
try {
FirebaseFirestore.instance
.collection("taks")
.doc(docIdTobeDeleted)
.delete()
.then((_) {
print("success!");
});
}
catch (e) {
print("ERROR DURING DELETE");
}
It should work.
your Listtile onTap will set the docID to the selected tileID.. and the deleteIconButton will delete the id of docID.. so if you tap on the first ListTile and tap on any of the deleteIconButton.. It will delete the first ListTile
You can use the direct ds.id instead of docID in the deleteIconButton
IconButton(
icon: Icon(
Icons.delete_outline,
size: 20.0,
color: Colors.brown[900],
),
onPressed: () async {
try {
FirebaseFirestore.instance
.collection("taks")
.doc(ds.Id)
.delete()
.then((_) {
print("success!");
});
}
catch (e) {
print("ERROR DURING DELETE");
}
// _onDeleteItemPressed(index);
},
),
I am trying to make a search feature in an app where I search for a store (from the Cloud Firestore database) using their query method where but I keep getting the same result, which is the first store on "list". No matter what I search.
StreamBuilder(
builder: (context , snapshot) {
if(snapshot.hasError) {
return Center(
child: Text(snapshot.error.toString()),
);
}//end if
if (snapshot.hasData) {
QuerySnapshot querysnapshot = snapshot.data;
List<QueryDocumentSnapshot> documents = querysnapshot.docs;
processData(documents);
print("here : " + stores[0].name.toString());
print("search: " + searchQuery);
print("array length: " + stores.length.toString());
return Container(
child: ListView.builder(
itemBuilder: (context , index) {
return Center(
child: Text(stores[index].name.toString()),
);
},
itemCount: stores.length,
),
height: height,
);
} else {
return Container(
child: Center(
child: Text("Snapshot has no data"),
),
);
}//end if-else
},
stream: FirebaseFirestore.instance.collection('Stores').where('name' , isEqualTo: name).snapshots(),
)
sorry I made an idiotic mistake. I forgot to use to search variable instead of the name variable in the where function!
Hello i have 2 screens in flutter the 1st page contains many JSON data like image,strings, etc to be pass in 2nd page how to to this? Thank in advance.
I have the my code below i stuck here for almost 4 hours now Can anybody help me.
//first page
Map data;
List userData;
Future getItems() async {
http.Response response = await http.get("MY_IP/olstore_serv/get_items");
data = json.decode(response.body);
setState(() {
userData = data["item"];
});
onTap: () {
Navigator.of(context, rootNavigator: true).push(
new CupertinoPageRoute(
builder: (context) {
return new ItemDetails(todo:userData);
},
),
);
},
/// second page
class ItemDetails extends StatelessWidget {
final List todo;
ItemDetails({this.todo});
#override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text('i want to display item name here pls help me'),
),
child: Container(
child: ListView(
physics: BouncingScrollPhysics(),
children: <Widget>[
Text('here too'),
]
),
),
);
}
}
Please try below code for listview.
ListView.builder(
itemCount: todo.length,
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Text(todo[index].yourKey);
},
);