How can I render an image from firestore database - flutter

I am working on a project and ended up having an error rendering the image from firestore and still do not understand what is exactly the problem. I am very new to Flutter.
Here is how I am uploading it
RoundedButton(
buttonName: 'Add Event',
onPressed: () async{
if(kIsWeb){
await uploadFileWeb().then((value) => showToast(
message: "Events Added Successfully",
color: Colors.green,
));
Navigator.pop(context);
}
else{
await uploadFile().then((value) => showToast(
message: "Events Added Successfully",
color: Colors.green,
));
Navigator.pop(context);
}
},
color: Colors.green,
),
and the functions
Future selectFile() async{
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
        allowMultiple: false,
        allowedExtensions: ['jpg']
    );
    if(result == null) return;
    final path = result.files.single.path!;
    setState(() {
      file = File(path);
    });
  }
  Future uploadFile() async{
    if(file == null) return;
    final fileName = basename(file!.path);
    final destination = 'events/$fileName';
    task = await FirebaseApi.uploadFile(destination, file!)!.then((_) async{
      DateTime time = DateTime.now();
      await FirebaseFirestore.instance.collection('activities').doc().set({
        'Name' : name,
        'Location': location,
        'Description' : description,
        'Price' : price,
        'Date' : date,
        'PhotoUrl': destination,
        'Type' : selectedType,
        'ts' : time,
      });
    });
  }
  void selectWebImage(){
    res.FileUploadInputElement uploadInput = res.FileUploadInputElement()..accept = 'image/*';
    uploadInput.click();
    uploadInput.onChange.listen((event) {
      webFile = uploadInput.files!.first;
      final reader = res.FileReader();
      reader.readAsDataUrl(webFile!);
      reader.onLoadEnd.listen((event) {
      });
    });
  }
  Future<void> uploadFileWeb()async {
    final dateTime = DateTime.now();
    final path = 'events/$dateTime';
    await FirebaseStorage.instance.refFromURL('gs://tembea-4d3c6.appspot.com')
        .child(path)
        .putBlob(webFile).then((_) async{
      DateTime time = DateTime.now();
      await FirebaseFirestore.instance.collection('activities').doc().set({
        'Name' : name,
        'Location': location,
        'Description' : description,
        'Price' : price,
        'Date' : date,
        'PhotoUrl': path,
        'Type' : selectedType,
        'ts' : time,
      });
    });
  }
}
This is how I am trying to retrieve data
final Stream<QuerySnapshot> activities = FirebaseFirestore
.instance.collection('activities').orderBy('ts', descending: true).snapshots();
StreamBuilder<QuerySnapshot>(
stream: activities,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return const Center(
child: CircularProgressIndicator(),
);
}
final data = snapshot.requireData;
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: data.size,
itemBuilder: (context, index){
if(data.docs[index]['Type'] == 'Event'){
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
backgroundColor: Colors.transparent,
radius: 40,
backgroundImage: NetworkImage(data.docs[index]['PhotoUrl']),
),
Text( data.docs[index]['Name'], style:const TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
Responsive.isWeb(context) ? ButtonBlue(
addLabel: 'Edit Event',
color: Colors.green,
onPressed: (){},
icon: const Icon(IconData(61161, fontFamily: 'MaterialIcons')),
) : InkWell(
onTap: (){},
child: const Icon(IconData(61161, fontFamily: 'MaterialIcons')),
),
Responsive.isWeb(context) ? ButtonBlue(
addLabel: 'Delete Event',
color: Colors.red,
onPressed: (){},
icon: const Icon(Icons.delete_outline,),
): InkWell(
onTap: (){},
child: const Icon(Icons.delete_outline,),
),
],
),
const Divider(
color: Colors.white70,
height:40.0,
),
],
);
}
return Container();
});
},
)
It keeps bringing me this error and I don't know what to do
Invalid argument(s): No host specified in URI file:///events/2021-11-16%2002:59:15.764
I have been on this the entire day and seem not to understand. Can anyone help me on this?

On Firestore you are saving document with final path = 'events/$dateTime'; as PhotoUrl, when retrieving it you are reading the string events/$dateTime and trying to use it as a URI for a NetworkImage.
NetworkImage is then trying to create a URI from that string which results in a local file uri and fails to download it from the network.
Basically, from what I see, you're not actually uploading a picture, but it's difficult to say without the complete code flow.

Related

Delete profile in firebase flutter

I need to delete the users profile from firebase, thing is I have 3 collections petfiles, petsdetails and users which need to be deleted. As in when a user signs up, they can create a pet and create records for their pet. But when having to delete the user, it should delete all the pets and records the pet has (it could be up to any amount)
I havent tried anything as I dont really know how to solve this but this is my code
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:image_picker/image_picker.dart';
import 'package:vet_bookr/oScreens/petFiles.dart';
import '../constant.dart';
class UserDetails extends StatefulWidget {
UserDetails({Key? key, required this.details}) : super(key: key);
Map<String, dynamic> details;
#override
State<UserDetails> createState() => _UserDetailsState();
}
class _UserDetailsState extends State<UserDetails> {
List<String> labels = ["Email", "Phone Number"];
bool editableText = false;
String imageUrl = "";
List<String> petIds = [];
#override
void initState() {
// TODO: implement initState
nameController.text = widget.details["name"];
ageController.text = widget.details["age"];
super.initState();
}
Future<void> uploadImages({required String path}) async {
try {
final imageRef = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await imageRef.putFile(File(path));
imageUrl = await imageRef.getDownloadURL();
setState(() {});
//print(imageRef.getDownloadURL());
} on FirebaseException catch (e) {
print("Function does work");
SnackBar snackBar = SnackBar(content: Text(e.message!));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
}
}
bool isLoading = false;
final nameController = TextEditingController();
final ageController = TextEditingController();
XFile? profilePic;
ImagePicker imagePicker = ImagePicker();
final storageRef = FirebaseStorage.instance.ref();
TextEditingController controllerChanger(index) {
if (index == 0) {
return nameController;
}
if (index == 1) {
return ageController;
}
return TextEditingController();
}
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
FocusScopeNode currentFocus = FocusScope.of(context);
if (!currentFocus.hasPrimaryFocus) {
currentFocus.unfocus();
}
},
child: Scaffold(
appBar: AppBar(
systemOverlayStyle: SystemUiOverlayStyle.dark,
backgroundColor: Colors.transparent,
elevation: 0,
leading: IconButton(
icon: Icon(
Icons.arrow_back,
color: Colors.black,
),
onPressed: () {
Navigator.pop(context);
},
),
actions: [
Padding(
padding: EdgeInsets.only(right: 5.sp),
child: PopupMenuButton(
icon: Icon(
Icons.more_vert,
color: Colors.black,
),
itemBuilder: (context) {
return [
PopupMenuItem<int>(
value: 0,
child: Text("Edit Profile"),
),
PopupMenuItem<int>(
value: 1,
child: Text("Delete Profile"),
),
];
},
onSelected: (value) async {
if (value == 0) {
setState(() {
editableText = true;
});
print(editableText);
} else if (value == 1) {
setState(() {
isLoading = true;
});
final ref = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await ref.delete();
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.delete();
DocumentSnapshot<Map<dynamic, dynamic>> snap =
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.get();
await FirebaseFirestore.instance
.collection("petDetails")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!),
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayUnion(snap.data()!["pets"]!),
});
setState(() {
isLoading = false;
});
Navigator.pop(context);
}
},
))
],
),
extendBodyBehindAppBar: true,
backgroundColor: kBackgroundColor,
body: isLoading
? Container(
width: 1.sw,
height: 0.4.sh,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: 15.sp,
width: 15.sp,
child: CircularProgressIndicator(
strokeWidth: 2,
color: Color(0xffFF8B6A),
),
),
],
),
)
: SafeArea(
child: Container(
//alignment: Alignment.center,
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(15.sp),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
// sBox(h: 10),
Text(
'Pet Information',
style: TextStyle(
color: Color(0xffF08519), fontSize: 0.05.sw),
),
// myPetTile()
SizedBox(
height: 0.05.sh,
),
Stack(
children: [
CircleAvatar(
radius: 0.095.sh,
backgroundColor: Color(0xffFF8B6A),
backgroundImage: profilePic == null
? NetworkImage(
widget.details["profilePicture"],
)
: null,
child: profilePic == null
? Container(
width: 0,
height: 0,
)
: ClipRRect(
borderRadius:
BorderRadius.circular(100),
child: Image.file(
File(
"${profilePic?.path}",
),
),
),
),
editableText
? Positioned(
right: 0.025.sw,
bottom: 0.005.sh,
child: GestureDetector(
onTap: () async {
profilePic = await ImagePicker()
.pickImage(
source: ImageSource.gallery);
setState(() {});
},
child: CircleAvatar(
backgroundColor: Color(0xffFF8B6A),
radius: 0.02.sh,
child: Icon(
Icons.camera_alt_outlined,
size: 0.05.sw,
color: Colors.white,
),
),
),
)
: Container(
width: 0,
height: 0,
)
],
),
SizedBox(
height: 0.02.sh,
),
...List.generate(
2,
(index) => Padding(
padding: EdgeInsets.only(
top: 0.02.sh, left: 0.05.sw, right: 0.05.sw),
child: TextField(
enabled: editableText,
controller: controllerChanger(index),
style: TextStyle(fontSize: 0.017.sh),
cursorColor: Colors.black,
decoration: InputDecoration(
label: Text(labels[index],
style: TextStyle(fontSize: 0.02.sh)),
labelStyle: TextStyle(color: Colors.black54),
focusedBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10.sp),
borderSide:
BorderSide(color: Color(0xffFF8B6A))),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10.sp),
),
enabledBorder: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10.sp),
borderSide:
BorderSide(color: Color(0xffFF8B6A))),
contentPadding:
EdgeInsets.symmetric(horizontal: 10.sp),
hintStyle: TextStyle(color: Colors.grey),
),
),
),
),
buttonWidget()
],
),
),
),
),
),
),
);
}
bool isLoadingEdit = false;
Widget buttonWidget() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Container(
width: 0.4.sw,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
padding: EdgeInsets.zero,
backgroundColor: Color(0xffFF8B6A),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.sp),
),
),
onPressed: () async {
if (editableText) {
setState(() {
isLoadingEdit = true;
});
if (profilePic != null) {
final ref = storageRef.child(
"Users/${FirebaseAuth.instance.currentUser?.uid}/${widget.details["id"]}");
await ref.delete();
await uploadImages(path: profilePic!.path);
}
await FirebaseFirestore.instance
.collection("petsDetails")
.doc(widget.details["id"])
.update({
'name': nameController.text,
'age': ageController.text,
'breed': breedController.text,
'weight': weightController.text,
'profilePicture': profilePic != null
? imageUrl
: widget.details["profilePicture"],
'lastVaccinationDate':
widget.details["lastVaccinationDate"]
});
DocumentSnapshot<Map<String, dynamic>> snap =
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.get();
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!)
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayRemove(snap.data()!["pets"]!),
});
await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser?.uid)
.update({
'pets': FieldValue.arrayUnion(snap.data()!["pets"]!),
});
Navigator.pop(context);
setState(() {
isLoadingEdit = false;
editableText = false;
});
const snackBar = SnackBar(
content: Text("Your pet's details have been changed"),
);
ScaffoldMessenger.of(context).showSnackBar(snackBar);
} else {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => PetFiles(
petId: widget.details["id"],
),
),
);
}
},
child: isLoadingEdit
? Container(
height: 15.sp,
width: 15.sp,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2.sp,
),
)
: Text(
editableText ? "Save Changes" : "Pet Health Records",
style:
TextStyle(color: Colors.white, fontSize: 0.03.sw),
),
),
),
],
),
SizedBox(
height: 0.01.sh,
),
],
);
}
}
You can check out their official docs for deleting collections here.
Or you can upgrade your project to blaze plan and use this extension which takes care of it for you.
Alternatively you can use NodeJS and FirebaseFunctions to do this task for you. Use this code snippet
async function deleteCollection(db, collectionPath, batchSize) {
const collectionRef = db.collection(collectionPath);
const query = collectionRef.orderBy('__name__').limit(batchSize);
return new Promise((resolve, reject) => {
deleteQueryBatch(db, query, resolve).catch(reject);
});
}
async function deleteQueryBatch(db, query, resolve) {
const snapshot = await query.get();
const batchSize = snapshot.size;
if (batchSize === 0) {
// When there are no documents left, we are done
resolve();
return;
}
// Delete documents in a batch
const batch = db.batch();
snapshot.docs.forEach((doc) => {
batch.delete(doc.ref);
});
await batch.commit();
// Recurse on the next process tick, to avoid
// exploding the stack.
process.nextTick(() => {
deleteQueryBatch(db, query, resolve);
});
}
index.js

How to persist and save value from shared prefernces in Flutter?

I want to persist value after user leaves page, also I would like to persist selected values, so I found out shared prefernces and I save it locally, but when I left page and return it remains unselected.
So I decided to convert my multipleSelected list to String, because sharedprefernces can't save list of ints and sfter that save selected values in lists. So how can i solve that problem when user leaves page and selected items become unselected.
class DataBaseUser extends StatefulWidget {
const DataBaseUser({Key? key}) : super(key: key);
#override
State<DataBaseUser> createState() => _DataBaseUserState();
}
class _DataBaseUserState extends State<DataBaseUser> {
int index = 1;
/// add selected items from list
List multipleSelected = [];
/// another list to form the new list above previous one
List chosenListsAbove = [];
List basesNames = [];
SharedPreferences? sharedPreferences;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Typographys.primaryColor,
appBar: PreferredSize(
preferredSize: const Size(125, 125),
child: AppBarService(),
),
body: Column(
children: [
// chosenOne(),
Card(
color: Typographys.gradientCard2,
child: ExpansionTile(
iconColor: Colors.white,
maintainState: true,
title: Text(
'Bases',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 35),
),
children: [
SizedBox(
height: 10,
),
getDataBaseList(),
SizedBox(
height: 22,
),
getUpdateBaseButtons(),
SizedBox(
height: 10,
),
],
),
),
],
),
);
}
Widget getDataBaseList() {
return FutureBuilder<List>(
future: BasesService().GetBases(),
builder: (context, snapshot) {
List? baseNames = snapshot.data;
print(baseNames);
return ListView.builder(
shrinkWrap: true,
itemCount: baseNames?.length ?? 0,
itemBuilder: (context, i) {
Future<void> _onCategorySelected(bool selected, id) async {
final pref = await SharedPreferences.getInstance();
if (selected == true) {
setState(() {
multipleSelected.add(id);
List<String> stringsList =
multipleSelected.map((i) => i.toString()).toList();
// store your string list in shared prefs
pref.setStringList("stringList", stringsList);
List<String> mList =
(pref.getStringList('stringList') ?? <String>[]);
print('HERE');
print(mList);
print('HERE 2');
});
} else {
setState(
() {
multipleSelected.remove(id);
},
);
}
}
return Column(
children: [
ListTile(
title: Padding(
padding: const EdgeInsets.only(left: 1.0),
child: Text(
baseNames?[i]['name'] ?? 'not loading',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
fontSize: 24,
fontWeight: FontWeight.w900,
color: Colors.white),
),
),
leading: Checkbox(
activeColor: Colors.green,
checkColor: Colors.green,
side: BorderSide(width: 2, color: Colors.white),
value: multipleSelected.contains(
baseNames?[i]['id'],
),
onChanged: (bool? selected) {
_onCategorySelected(selected!, baseNames?[i]['id']);
},
)
//you can use checkboxlistTile too
),
],
);
},
);
},
);
}
Widget getUpdateBaseButtons() {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
FutureBuilder<bool>(
future: BasesService().SelectBaseAsync(multipleSelected.cast()),
builder: (context, snapshot) {
return ElevatedButton(
onPressed: () {
if (snapshot.data == true) {
BasesService().SelectBaseAsync(multipleSelected.cast());
print(multipleSelected.cast());
print(multipleSelected);
successSnackBar();
} else {
notSuccessSnackBar();
}
},
child: Text(
'Send bases',
style: TextStyle(
fontFamily: 'fonts/Montserrat',
fontSize: 22,
fontWeight: FontWeight.w900,
color: Colors.white,
letterSpacing: 2),
),
style: ElevatedButton.styleFrom(
minimumSize: Size(200, 40),
primary: Colors.green,
onPrimary: Colors.white,
),
);
return Container();
})
],
),
);
}
If I understand you correclty, cant you just save items in WillPopScope like
return WillPopScope(
onWillPop: () async => SaveMyPreferences,
child: const Scaffold(
body: Container(
color: Colors.red,
size: 50.0,
),
),
);
I found a solution. If your data that you want to save comes from the API and is constantly updated (as it was in my case), then you do not need to use the shared preference package. This package will not help you. In my case, in order to save the checkboxes selected by the user and after reloading the page to show him which items in the list were selected (I use checkboxes), I write to a file on the device and then read the saved data from this file. So you are going to need path_provider package and dart:io and these two functions
to write from function where you choose items
_onCategorySelected(bool selected, id) async {
final Directory directory =
await getApplicationDocumentsDirectory();
if (selected == true) {
multipleSelected.add(id);
} else {
multipleSelected.remove(id);
}
final File file = File('${directory.path}/my_file.json');
file.writeAsStringSync('{"selected": $multipleSelected}');
setState(() {});
}
to read from file:
Future<String> read() async {
String text = '';
try {
final Directory directory =
await getApplicationDocumentsDirectory();
final File file = File('${directory.path}/my_file.json');
text = await file.readAsString();
print('HELLO');
multipleSelected = json.decode(text)["selected"];
} catch (e) {
print("Couldn't read file");
}
return text;
}
and before the listview.builder comes, you need to use read() function ro read the saved values from file.
It is not the greatest solution (maybe, the worst one), but if you haven't got enough time and you don't have any state management and you just need to solve issue right now, it can be really helpfull.

Keep getting error when trying to upload image to Firebase Storage in Flutter

The image is not uploading getting the error is "The server has terminated the upload session User does not have permission to access this object". I change my security rules of Storage but again got the same error
import 'dart:io';
class _HomeScreenState extends State<HomeScreen> {
Image? childImage;
TextEditingController childNameController = TextEditingController();
TextEditingController childAgeController = TextEditingController();
TextEditingController childDiagnosisController = TextEditingController();
GlobalKey<FormState> _formKey = GlobalKey();
FocusNode _childNameFocus = FocusNode();
FocusNode _childAgeFocus = FocusNode();
FocusNode _childDiagnosisFocus = FocusNode();
String buttonText = 'Image';
String get _childName => childNameController.text;
void _nameEditingComplete() {
final newFocus = widget.nameValidator.isValid(_childName)
? _childAgeFocus
: _childNameFocus;
FocusScope.of(context).requestFocus(newFocus);
}
Future<void> writeChildrenToDb(
String parentUid,
String childUid,
String childNameInput,
String childAgeInput,
String childDiagnosisInput,
String childPicUrl) async {
FirebaseFirestore.instance
.collection('users')
.doc(parentUid)
.collection('children')
.doc(childUid)
.set({
'childName': childNameInput,
'childAge': childAgeInput,
'childDiagnosis': childDiagnosisInput,
'childUid': childUid,
'childPicUrl': childPicUrl,
});
} // writes children details to db
Future<String> uploadImageToFirebase(String childUid, File img) async {
Reference storage = FirebaseStorage.instance
.ref()
.child('users/$parentIdGlobal/$childUid/child_pic');
UploadTask uploadTask = storage.putFile(img);
var dowurl = await (await uploadTask).ref.getDownloadURL();
var url = dowurl.toString();
return url;
}
_showAddDialog() {
String? childUid = Uuid().v4();
String? childNameInput;
String? childAgeInput;
String? childDiagnosisInput;
String? childPicUrl;
File? pickedImage;
bool imgStatus = true;
return showDialog(
context: context,
builder: (context) => StatefulBuilder(
builder: (context, setState) => AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(
10.0,
),
),
title: Text(
'Add Child Information',
),
contentPadding: EdgeInsets.all(8.0),
elevation: 10.0,
content: SingleChildScrollView(
child: Form(
key: _formKey,
child: Column(
children: <Widget>[
SizedBox(
height: 10.0,
),
Here is my image path portion. My image appears in the dialogue box, but it does not print or upload to the Firebase Cloud.
GestureDetector(
onTap: () async {
await Permission.photos.request();
var status = await Permission.photos.status;
if (status.isGranted) {
XFile? _pickedImage = await ImagePicker().pickImage(
source: ImageSource.gallery,
maxWidth: 100,
maxHeight: 100,
);
if (_pickedImage != null) {
pickedImage = File(_pickedImage.path);
setState(() {
imgStatus = true;
});
}
} else if (status.isDenied ||
status.isPermanentlyDenied) {
showDialog(
context: context,
builder: (context) {
if (Platform.isAndroid)
return AlertDialog(
title: Text('Permission Not Granted'),
content: Text(
'The permission for photo library is not granted'),
actions: [
TextButton(
onPressed: () => openAppSettings(),
child: Text('Ok'),
),
],
);
return CupertinoAlertDialog(
title: Text('Permission Not Granted'),
content: Text(
'The permission for photo library is not granted'),
actions: [
TextButton(
onPressed: () => openAppSettings(),
child: Text('Ok'),
),
],
);
});
}
},
child: Padding(
padding: EdgeInsets.only(
top: 10.0,
bottom: 10.0,
),
child: Container(
height: 100.0,
width: 100.0,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.transparent,
border: Border.all(
style: BorderStyle.solid,
),
),
child: pickedImage == null
? Icon(
Icons.add,
color: Colors.black,
)
: Image.file(
pickedImage!,
fit: BoxFit.contain,
),
),
),
),
],
),
),
),
actions: <Widget>[
TextButton(
onPressed: () {
childNameController.clear();
childAgeController.clear();
Navigator.of(context).pop();
},
child: Text('Cancel'),
),
TextButton(
onPressed: imgStatus
?() async {
childNameInput = childNameController.text;
childAgeInput = childAgeController.text;
childDiagnosisInput = childDiagnosisController.text;
String parentUid = await getData('parentUid') ?? '';
if (_formKey.currentState?.validate() ?? true) {
if (pickedImage != null) {
childPicUrl =
await uploadImageToFirebase(childUid, pickedImage!);
}
await writeChildrenToDb(parentUid, childUid, childNameInput!,
childAgeInput!, childDiagnosisInput!, childPicUrl!);
childNameController.clear();
childAgeController.clear();
Navigator.of(context).pop();
}
}: null,
child: Text('Ok'),
),
],
),
),
);
}
security rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write
}
}
}

flutter firestore - How to retrieve the new document id after adding to firestore

I want to retrieve the new created document id and display the document data in a new page. How can i get the document id? When onPressed() the elevated button, I want to retrieve the document data based on its id.
How can I bring the document id from addDiagnose(_type, _symptomsResult) so that I can navigate it to another page.
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DiagnosisPage(documentId: documentId),
)
);
This is my current code.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:multiselect_formfield/multiselect_formfield.dart';
import 'package:petbuddies/user/diagnosis/diagnose_history.dart';
import 'package:petbuddies/user/diagnosis/diagnosis.dart';
class CheckerPage extends StatefulWidget {
const CheckerPage({Key? key}) : super(key: key);
#override
_CheckerPageState createState() => _CheckerPageState();
}
class _CheckerPageState extends State<CheckerPage> {
//retrieve options
final _formKey = GlobalKey<FormState>();
void _petTypeDropDownItemSelected(String newValueSelected) {
setState(() {
petType = newValueSelected;
});
}
clearText(){
_symptoms?.clear();
}
#override
void initState(){
super.initState();
_symptoms = [];
_symptomsResult = [];
}
List? _symptoms;
late List<dynamic> _symptomsResult;
var petType;
var _type;
final Stream<QuerySnapshot> petTypeStream = FirebaseFirestore.instance.collection('pet type').orderBy('name').snapshots();
final Stream<QuerySnapshot> symptomsStream = FirebaseFirestore.instance.collection('symptoms').orderBy('name').snapshots();
DocumentReference diagnosis = FirebaseFirestore.instance.collection('diagnosis').doc();
//store the diagnosis result
User? user = FirebaseAuth.instance.currentUser;
Future<void> addDiagnose(_type, _symptomsResult) async {
String petChosen = this._type;
List symptomsChosen = this._symptomsResult.toList();
QuerySnapshot<Map<String, dynamic>> snapshot =
await FirebaseFirestore.instance.collection("disease")
.where('petType',isEqualTo: petChosen)
.where('symptoms',arrayContainsAny: symptomsChosen)
.get();
List<String> diseaseRef = snapshot.docs.map((e) => e.id).toList();
String createdby = user!.uid;
Timestamp date = Timestamp.now();
List possibleDisease = diseaseRef.toList();
final data = {
'created by': createdby,
'date': date,
'pet chosen': petChosen,
'symptoms chosen': symptomsChosen,
'possible disease': possibleDisease,
};
//set document data
return diagnosis
.set(data)
.then((value) => print('Diagnose Report Added'))
.catchError((error)=>print("Failed to add: $error")
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.blue[900],
title: const Text("Pet Symptoms Checker",
style: TextStyle(color: Colors.white),
),
),
body: Form(
key: _formKey,
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 20, horizontal: 30),
child: ListView(
children: [
Align(
alignment: Alignment.bottomRight,
child: TextButton(
child: const Text(
'History',
style: TextStyle(fontSize: 18),
),
onPressed: (){
Navigator.push(context, MaterialPageRoute(builder: (context) => const DiagnoseHistoryPage(),));
},
),
),
Container(
padding: const EdgeInsets.all(12.0),
decoration: BoxDecoration(
border: Border.all(width: 3, color: Colors.indigo,),
borderRadius: const BorderRadius.all(Radius.circular(30)),
),
child: Column(
children: [
StreamBuilder<QuerySnapshot>(
stream: petTypeStream,
builder: (context, snapshot) {
if (!snapshot.hasData) {
return const Center(
child: CircularProgressIndicator(),
);
}
return Container(
padding: const EdgeInsets.only(bottom: 16.0),
child: Row(
children: <Widget>[
Expanded(
flex: 2,
child: Container(
padding: const EdgeInsets.fromLTRB(12.0, 10.0, 10.0, 10.0),
child: const Text(
"Pet Type",
style: TextStyle(fontSize: 20),
),
),
),
Expanded(
flex: 3,
child: Row(
children: [
const SizedBox(width: 30,),
DropdownButton(
value: petType,
onChanged: (valueSelectedByUser) {
_petTypeDropDownItemSelected(valueSelectedByUser.toString());
},
hint: const Text('Choose Pet Type',),
underline: Container(),
items: snapshot.data!.docs.map((DocumentSnapshot document) {
return DropdownMenuItem<String>(
value: document.get('name'),
child: Text(document.get('name')),
);
}).toList(),
),
],
),
),
],
),
);
}),
StreamBuilder(
stream: symptomsStream,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot){
if(snapshot.hasError){
print('Something went wrong');
}
if(snapshot.connectionState == ConnectionState.waiting){
return const Center(
child: CircularProgressIndicator(),
);
}
final List symptomsList = [];
snapshot.data!.docs.map((DocumentSnapshot document){
Map a = document.data() as Map<String, dynamic>;
symptomsList.add(a['name']);
a['id'] = document.id;
}).toList();
return MultiSelectFormField(
autovalidate: AutovalidateMode.disabled,
chipBackGroundColor: Colors.blue[900],
chipLabelStyle: const TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
dialogTextStyle: const TextStyle(fontWeight: FontWeight.bold),
checkBoxActiveColor: Colors.blue[900],
checkBoxCheckColor: Colors.white,
dialogShapeBorder: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0))),
title: const Text(
"Symptoms",
style: TextStyle(fontSize:20),
),
validator: (value) {
if (value == null || value.length == 0) {
return 'Please select one or more symptoms';
}
return null;
},
dataSource: [
for (String i in symptomsList) {'value' : i}
],
textField: 'value',
valueField: 'value',
okButtonLabel: 'OK',
cancelButtonLabel: 'CANCEL',
hintWidget: const Text('Please choose one or more symptoms'),
initialValue: _symptoms,
onSaved: (value) {
if (value == null) return;
setState(() {
_symptoms = value;
}
);
},
);
}
),
const SizedBox(height:50,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
onPressed: () async{
if(_formKey.currentState!.validate()){
setState(() {
_type = petType.toString();
_symptomsResult = _symptoms!.toList();
addDiagnose(_type,_symptomsResult);
final documentId = diagnosis.id;
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => DiagnosisPage(documentId: documentId),
)
);
clearText();
}
);
}
},
child: const Text(
'Diagnose',
style: TextStyle(fontSize: 18),
),
style: ElevatedButton.styleFrom(primary: Colors.blue[900]),
),
],
),
],
),
)
],
),
),
),
);
}
}

Flutter, How to search instantly in sqflite database?

When I search for any poet it always gives me the first records. it does not show the exact record that I am searching for.
My TasksPage:
TextEditingController _searchInputController = TextEditingController();
var list = [];
var filteredList = [];
bool doItJustOnce = false;
void _filterList(value) {
setState(() {
filteredList = list
.where((text) => text.name.toLowerCase().contains(value.toLowerCase())).toList();
});}
The TextField through which I search the desired record
TextField(
onChanged: (value) {
setState(() {
// _filterList(value);
});
},
),
The FutureBuilder
FutureBuilder<List<Poets>>(
//we call the method, which is in the folder db file database.dart
future: DatabaseHelper.instance.getPoets(),
builder: (BuildContext context, AsyncSnapshot<List<Poets>> snapshot) {
if (snapshot.hasData) {
if (!doItJustOnce) {
//You should define a bool like (bool doItJustOnce = false;) on your state.
list = snapshot.data!;
filteredList = list;
doItJustOnce = !doItJustOnce; //this line helps to do just once.
}
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 7),
physics: BouncingScrollPhysics(),
reverse: false,
//Count all records
itemCount: snapshot.data!.length,
// itemCount: filteredList.length, // snapshot.data!.length, //filterLis.length,
//all the records that are in the Student table are passed to an item Poet item = snapshot.data [index];
itemBuilder: (BuildContext context, int index) {
Poets item = snapshot.data![index];
//delete one register for id
return Dismissible(
key: UniqueKey(),
background: Container(
color: Colors.red,
child: Padding(
padding: const EdgeInsets.fromLTRB(338, 30, 0, 0),
child: Text(
'Delete',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
onDismissed: (direction) {
setState(() {
DatabaseHelper.instance.remove(item.id);
});
},
//Now we paint the list with all the records, which will have a number, name, phone
child: Card(
elevation: 15.0,
color: Colors.white12,
child: Container(
decoration: BoxDecoration(
// color: Color.fromRGBO(64, 75, 96, .9,),
color: Colors.white70,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
),
child: ListTile(
leading: CircleAvatar(
child: Text(item.id.toString()),
backgroundColor: Color.fromRGBO(
64,
75,
96,
.9,
),
foregroundColor: Colors.white,
),
title: Text(
item.name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(item.f_name),
trailing: Text(item.serial_no.toString()),
//If we press one of the cards, it takes us to the page to edit, with the data onTap:
//This method is in the file add_editclient.dart
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AddEditClient(
true,
//Here is the record that we want to edit
poet: item,
)));
},
// onLongPress: () {
// setState(() {
// DatabaseHelper.instance.remove(item.id);
// });
// },
),
),
),
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
My Question is How to search in sqflite database,please help me.
you can use this sqflite package that will make your task very easy on the query side. you can find an example on its repository(GitHub).
or you can try this,
Future getSearch async(){try {
var mapList = await DbHelper.getTaskDetail(
table: 'CustomerDetails', where: 'name= joe');
if (mapList != null && mapList.isNotEmpty) {
yourlist.clear()
yourlist
.addAll(mapList.map((e) => yourmodel.fromJson(e)).toList());
}
}catch(Exception e){
}}
static Future<List<Map<String, dynamic>>?> getTaskDetail(
{required String table,
String? query,
String? orderBy,
String? where,
int? limit}) async {
final db = await instance.taskDatabase;
return db?.query(table, orderBy: orderBy, limit: limit, where: where);}
put your result in setState().