Flutter Firestore Read specific field from specific document via stream function - firebase

basically im struggling to create a function in my database.dart where i can call this function to display a specfic field in a specific document.
Example, i want to use Database.readUserProfileData('Profile', 'surname') to display the string/alt to a widget.
static Future<QuerySnapshot> readUserProfileData({
required String docId,
required String field,
}) async {
var ref = _mainCollection.get().then((querySnapshot) {
querySnapshot.docs.forEach((result) {
Object? data = result.data();
print(data);
});
});
}
Here is my database.dart
(please ignore the UpdateItem function as i have not configured it properly as i copied this from a template, or maybe update it for me lol sorry ;))
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
/* ------------------ Database Reference - Main Collection ------------------ */
final CollectionReference _mainCollection = _firestore.collection('_TestFB');
class Database {
static String? userUid;
/* -------------------------- Create User Database -------------------------- */
static Future<void> createUserDataFile({
required String uid,
required String surname,
required int mobile,
}) async {
DocumentReference documentReferencer =
_mainCollection.doc('UserData').collection(uid).doc('Profile');
Map<String, dynamic> data = <String, dynamic>{
"surname": surname,
"mobile": mobile,
};
_mainCollection
.doc('UserData')
.collection(uid)
.limit(1)
.get()
.then((snapshot) async {
if (snapshot.size == 1) {
print("**User Profile Exists");
} else {
await documentReferencer
.set(data)
.whenComplete(() => print("**New Profile Created for - " + uid))
.catchError((e) => print(e));
}
});
}
/* ------------------------- Read User Profile Data ------------------------- */
static Future<QuerySnapshot> readUserProfileData({
required String docId,
required String field,
}) async {
var ref = _mainCollection.get().then((querySnapshot) {
querySnapshot.docs.forEach((result) {
Object? data = result.data();
print(data);
});
});
}
Thanks in Advance

If you already have the document id, then just do:
static Future<DocumentSnapshot> readUserProfileData({
required String docId,
required String field,
}) async {
var ref = _mainCollection.doc(docId).get().then((snapshot) {
print(snapshot);
print(snapshot.data()[field]);
});
}
You don't need to use forEach since you are only retrieving one document and get() will have a return type Future<DocumentSnapshot>

Related

How to display all the names in database firestorefirebase flutter

In my app I have a model which consists of the store name and store image and looks like this:
class StoreModel
{
String? imageofStore;
String? storeName;
StoreModel({ this.imageofStore, this.storeName});
//data from server
factory StoreModel.fromMap(map)
{
return StoreModel(
imageofStore: map['imageofStore'],
storeName: map['storeName'],
);
}
// data to server
Map<String, dynamic> toMap(){
return{
'imageofStore': imageofStore,
'storeName': storeName,
};
}
}
and my database for stores looks like this:
to call the store name I use initstate and setState as such:
class addStore extends StatefulWidget {
const addStore({Key? key}) : super(key: key);
#override
_addStoreState createState() => _addStoreState();
}
class _addStoreState extends State<addStore> {
User ? user = FirebaseAuth.instance.currentUser;
StoreModel storebox = StoreModel();
#override
void initState()
{
super.initState();
FirebaseFirestore.instance
.collection("stores")
.doc("XQjbm665g2a2xAiiydjr")
.get()
.then((value){
this.storebox = StoreModel.fromMap(value.data());
setState(() {
});
});
}
#override
Widget build(BuildContext context) {
return Container(
child: Text("${storebox.storeName}"),
);
}
}
With this, I get the store name of the store with id XQjbm665g2a2xAiiydjr displaying but the thing is I want to get the name of all the stores. I know I need to change the .doc() but im not sure as to what I am to put in it that will start displaying all the names. Can someone please help?
By providing a document id, what you're getting is a DocumentSnapshot which is the data of a particular Document, but when you remove it, you get QuerySnapshot which is a list of the data of all the documents. So, to read all, you change your code as:
List<StoreModel> storesList = [];
FirebaseFirestore.instance
.collection("stores")
.get()
.then((value){
//Now, this value is of type QuerySnapshot unlike earlier.
if (value != null && value.docs.isNotEmpty) {
//If it comes here means the collection is not empty.
//Because this value is a list of DocumentSnapshot, We've to map it to extract documents.
//After mapping, returning it as a list and assigning it to storesList
storesList = value.docs.map((doc) => StoreModel.fromMap(doc.data())).toList();
setState(() {
});
} else {
//If it comes here means there are no documents in your collection.
//Notify User there's no data.
}
});
This code will get all the documents your collection have, but, you can limit or filter using limit or where respectively, just place .limit(int) or .where() before .get().
for model try to convert to json or you can use your either way this is just for example model
import 'dart:convert';
List<StoreModel> storeModelFromJson(String str) => List<StoreModel>.from(json.decode(str).map((x) => StoreModel.fromJson(x)));
String storeModelToJson(List<StoreModel> data) => json.encode(List<dynamic>.from(data.map((x) => x.toJson())));
class StoreModel {
StoreModel({
this.imageofStore,
this.storeName,
});
final String? imageofStore;
final String? storeName;
factory StoreModel.fromJson(Map<String, dynamic> json) => StoreModel(
imageofStore: json["imageofStore"] == null ? null : json["imageofStore"]!,
storeName: json["storeName"] == null ? null : json["storeName"]!,
);
Map<String, dynamic> toJson() => {
"imageofStore": imageofStore == null ? null : imageofStore!,
"storeName": storeName == null ? null : storeName!,
};
}
try this get all list
static Future<List<StoreModel>> getStorelist() async {
List<dynamic> list = [];
await FirebaseFirestore.instance
.collection("stores")
.get()
.then((value){
for(var x in value.docs){
final Map<String,dynamic> toMap = x.data() as Map<String,dynamic>;
/// Try to print all data first to see if fetching use log to view on terminal
log(toMap.toString());
list.add(toMap);
}
});
return list.map((e)= > StoreModel.fromJson(e)).toList();
}
as in my case to get only 1 data
static getSingleName(String? uid) async {
final result =
await FirebaseFirestore.instance
.collection("stores").doc(uid).get();
final response = result.data() as Map<String, dynamic>;
return response['storeName'].toString();
}

Flutter Firebase async query not retrieving data inside a stream function

I am trying to query a User from firebase within another query but for some reason but I can't get the code to work
The function the wont run is await usersRef.doc(uid).get(); and can be found here:
static getUserData(String uid) async {
return await usersRef.doc(uid).get();
}
static DirectMessageListModel getDocData(QueryDocumentSnapshot qdoc, String uid) {
Userdata postUser = Userdata.fromDoc(getUserData(uid));
return DirectMessageListModel.fromDoc(qdoc, postUser);
}
static DirectMessageListModel fromDoc(QueryDocumentSnapshot doc, Userdata altUser) {
return DirectMessageListModel(
doc['chatId'],
doc['lastMsgContent'],
doc['lastMsgType'],
altUser
);
}
parent function:
Stream<List<DirectMessageListModel>> getMeassageList(){
var snaps = FirebaseFirestore.instance.collection('directMessages').where('users', arrayContains: userdata!.uid).snapshots();
List<String> usersListElement = [];
return snaps.map((event) { return event.docs.map((e) {
usersListElement = [e.get('users')[0], e.get('users')[1]];
usersListElement.remove(userdata!.uid);
return DirectMessageListModel.getDocData(e, usersListElement.first);
}).toList();
});
}
You forgot to wait for the future getUserData(uid) to complete.
Try this:
static Future<DocumentSnapshot<Object>> getUserData(String uid) async {
return await usersRef.doc(uid).get();
}
static DirectMessageListModel getDocData(
QueryDocumentSnapshot qdoc,
String uid,
) async {
Userdata postUser = Userdata.fromDoc(await getUserData(uid)); // await here
return DirectMessageListModel.fromDoc(qdoc, postUser);
}
..
// parent function.
// Also wait for the future in the parent function.
// UPDATE BELOW! Define the parent function like this:
Stream<List<Future<DirectMessageListModel>>> getMeassageList() {
var snaps = FirebaseFirestore.instance
.collection('directMessages')
.where('users', arrayContains: userdata!.uid)
.snapshots();
List<String> usersListElement = [];
return snaps.map((event) {
return event.docs.map((e) async {
usersListElement = [e.get('users')[0], e.get('users')[1]];
usersListElement.remove(userdata!.uid);
return await DirectMessageListModel.getDocData(e, usersListElement.first);
}).toList();
});
}
NB: You are fetching user data (either sender/receiver) for each message in directMessages collection. It might be better to store just sender/receiver name in directMessages collection and simply display that. Then if the user clicks on a message, you can then fetch the full sender/receiver data.

Map an Array of objects from Firebase to List Flutter

I'm trying to retrieve an array of objects from Firebase and store it in Flutter Object as a List.
This is the collection, Firebase,
And this is the model class
class Merchant {
String shopName;
String address;
String description;
String thumbNail;
LatLng locationCoords;
Merchant(
{this.shopName,
this.address,
this.description,
this.thumbNail,
this.locationCoords});
}
final List<Merchant> merchant = []; // Map it to This List
I'd like to map it into this list above
final List<Merchant> merchant = [];
First add this method to your Merchant class:
Merchant.fromMap(Map<String, dynamic> map) {
shopName = map['shopName'];
address = map['address'];
description = map['description'];
thumbnail = map['thumbnail'];
locationCoords = map['locationCoords'];
}
This method will then be used to write the data into the Merchant Class/Struct.
Retrieving the data the could look something like the following:
import 'package:cloud_firestore/cloud_firestore.dart';
FirebaseFirestore _firestore = FirebaseFirestore.instance;
CollectionReference merchRef = _firestore.collection('merchants'));
Future<List<Merchant>> getAllMerchants() async {
List<Merchant> merchantList = [];
await merchRef.get().then((QuerySnapshot querySnapshot) {
querySnapshot.docs.forEach((doc) {
Merchant merchant = Merchant.fromMap({
'shopName': doc['shopname'],
'address': doc['address'],
'description': doc['description'],
'thumbnail': doc['thumbnail'],
'locationCoords': doc['location'],
});
merchantList.add(merchant);
});
});
return merchantList;
}
P.S.:
HavenĀ“t tried this out yet and you might need some parsing for locationCoords, since it is of type LatLng.

Fluttet sqfLite delete

I am trying to build a note app. I watch some tutorials on sqflite in order to save data after the app is terminated. I have managed to save the data but i cant delete data.
Here is the DBelper class i have created:
import 'package:sqflite/sqflite.dart' as sql;
import 'package:path/path.dart' as path;
import 'package:sqflite/sqlite_api.dart';
class DBHelper {
static Future<Database> databse() async {
final dbPath = await sql.getDatabasesPath();
return sql.openDatabase(path.join(dbPath, 'notes.db'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE user_notes(id TEXT PRIMARY KEY, title TEXT, text TEXT)');
}, version: 1);
}
static Future<void> insert(String table, Map<String, Object> data) async {
final db = await DBHelper.databse();
db.insert(
table,
data,
);
}
static Future<List<Map<String, dynamic>>> getData(String table) async {
final db = await DBHelper.databse();
return db.query(table);
}
}
And this is how i save the data :
onPressed: () {
Provider.of<Notes>(context, listen: false)
.addNote(newNoteTitle, newNoteText);
DBHelper.insert('user_notes',
{'title': newNoteTitle, 'text': newNoteText});
Navigator.pop(context);
},
I have been trying to create the DBHelper.deleteNote but even if i manage to write some code without errors nothing gets deleted. Thanks in advance for any help
If you simply want to delete a note then you can use its id, something like this:
deleteNote(String id) async {
final db = await DBHelper.databse();
db.delete('user_notes', where: 'id = ?', whereArgs: [id]);
}

How to store image in fire base and store url in firestore

i want to send coupon card to fire store that contain ( name - address - coupon ) and i want to make user set an specific image for every single card
that's my FireStoreService file
class FireStoreService {
FireStoreService._internal();
static final FireStoreService firestoreService = FireStoreService._internal();
Firestore db = Firestore.instance ;
factory FireStoreService() {
return firestoreService;
}
Stream<List<Coupon>> getCoupon() {
return db.collection('coupon').snapshots().map(
(snapshot) => snapshot.documents.map(
(doc) => Coupon.fromMap(doc.data, doc.documentID),
).toList(),
);
}
Future<void> addCoupon(Coupon coupon) {
return db.collection('coupon').add(coupon.toMap());
}
Future<void> deleteCoupon(String id) {
return db.collection('coupon').document(id).delete();
}
Future<void> updateCoupon(Coupon coupon) {
return db.collection('coupon').document(coupon.id).updateData(coupon.toMap());
}
}
and this is Coupon Model file
class Coupon {
final String id;
final String storeName;
final String storeLink;
final String couponCode;
Coupon(
{this.id, this.storeName, this.storeLink, this.couponCode});
Coupon.fromMap(Map<String, dynamic> data, String id)
: storeName = data["storeName"],
storeLink = data['storeLink'],
couponCode = data["couponCode"],
id = id;
Map<String, dynamic> toMap() {
return {
"storeName": storeName,
'storeLink': storeLink,
'couponCode': couponCode,
};
}
}
and this is Image Picker code and it's work fine and picked up the image
Future getImage() async {
try {
File image = await ImagePicker.pickImage(source: ImageSource.gallery);
setState(() {
image = image;
});
} catch (e) {
print(e);
}
}
any help ?
This is a function that asks for an imageFile. If you run your code (getImage function): pass the image variable to the uploadImage function.
String myUrl = await uploadImage(file);
Then you can use setData or updateData to put the url in the database.
Firestore.instance.collection('books').document()
.setData({ 'title': 'title', 'url': '$myUrl' })
final StorageReference storageRef = FirebaseStorage.instance.ref();
Future<String> uploadImage(imageFile) async {
StorageUploadTask uploadTask =
storageRef.child("myPath&Name.jpg").putFile(imageFile);
StorageTaskSnapshot storageSnap = await uploadTask.onComplete;
String downloadURL = await storageSnap.ref.getDownloadURL();
return downloadURL;
}

Resources