FirebaseFirestore - Snapshot with 'where' - firebase

Does anyone have a example for using the 'where' in the snapshot for FirebaseFirestore?
As I want to listen to the documents where one of the fields are equal to a specific email.
This I want then to use to update my Scaffold to display the current settings.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
class Test2 extends StatelessWidget {
const Test2({Key? key}) : super(key: key);
static const String id = 'test_2';
final TextEditingController _deviceName = TextEditingController();
final TextEditingController _onHour = TextEditingController();
#override
var firebaseUser = FirebaseAuth.instance.currentUser?.email;
final CollectionReference _device =
FirebaseFirestore.instance.collection('devices').where('email', isEqualTo: '$firebaseUser') as CollectionReference<Object?>;
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(leading: null,
actions: [
IconButton(
onPressed: () {},
icon: Icon(Icons.close))
],
title: const Text('Device Selection page'),),
body: StreamBuilder(
stream: _device.snapshots(),
builder: (context, AsyncSnapshot<QuerySnapshot> streamSnapshot) {
if (streamSnapshot.hasData) {
return ListView.builder(
itemCount: streamSnapshot.data!.docs.length,
itemBuilder: (context, index) {
final DocumentSnapshot documentSnapshot = streamSnapshot.data!
.docs[index];
return Card(
margin: const EdgeInsets.all(10),
child: ListTile(
title: Text(documentSnapshot['deviceName']),
subtitle: Text(documentSnapshot['startHour'].toString()),
trailing: SizedBox(
width: 100,
child: Row(
children: [IconButton(
onPressed: () {}, icon: const Icon(Icons.edit)),
IconButton(onPressed: () {},
icon: const Icon(Icons.delete))
],
),
),
),
);
},);
};
return Container(
child: Row(
children: [Text('Test')],
),
);
},
)
);
}
}

Related

Flutter Firebase - App Becomes Unresponsive When Expanding Exoansion Tiles

Trying to use some nested streambuilders, listview builders and expansion tiles to display data from Firestore, app freezes until terminated when I try to expand the tiles.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firestore_troubleshooting/models/class1.dart';
import 'package:firestore_troubleshooting/services/auth_service.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'models/class2.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await AuthService().getOrCreateUser();
runApp(const MyApp());
}
late var class1Data;
late var class2Data;
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
backgroundColor: Colors.grey[800],
textTheme: Theme.of(context)
.textTheme
.apply(bodyColor: Colors.white, displayColor: Colors.white),
splashColor: Colors.grey[800],
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Firestore Troubleshooting'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
TextEditingController textController1 = TextEditingController();
final Stream<QuerySnapshot> class1Stream = FirebaseFirestore.instance
.collection('users')
.doc(AuthService().currentUser?.uid)
.collection('Class 1 Objects')
.snapshots();
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[800],
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(children: [
Expanded(
child: TextField(
controller: textController1,
),
),
Expanded(
child: ElevatedButton(
onPressed: () {
createClass1Object(textController1.text);
textController1.clear();
setState(() {});
},
child: Text('Add Object')))
]),
StreamBuilder(
stream: class1Stream,
builder: (context, class1Snapshot) {
if (class1Snapshot.hasError) {
return Text('client snapshot has error');
}
if (class1Snapshot.connectionState ==
ConnectionState.waiting) {
return CircularProgressIndicator();
}
class1Data = class1Snapshot.requireData;
return ListView.builder(
shrinkWrap: true,
itemCount: class1Data.size,
itemBuilder: (context, class1_index) {
final Stream<QuerySnapshot> class2Stream =
FirebaseFirestore.instance
.collection('users')
.doc(AuthService().currentUser?.uid)
.collection('Class 1 Objects')
.doc(class1Data.docs[class1_index]['docID'])
.collection('Class 2 Objects')
.snapshots();
return class1Data.size > 0
? ExpansionTile(
initiallyExpanded: true,
title:
Text(class1Data.docs[class1_index]['name']),
children: [
Row(children: [
Expanded(
child: TextField(
controller: textController1,
),
),
Expanded(
child: ElevatedButton(
onPressed: () {
createClass2Object(
textController1.text,
class1_index);
textController1.clear();
setState(() {});
},
child: Text('Add Object')))
]),
StreamBuilder(
stream: class2Stream,
builder: (context, class2Snapshot) {
if (class2Snapshot.hasError) {
return Text(
'client snapshot has error');
}
if (class2Snapshot.connectionState ==
ConnectionState.waiting) {
return CircularProgressIndicator();
}
class2Data = class2Snapshot.requireData;
return ListView.builder(
shrinkWrap: true,
itemCount: class2Data.size,
itemBuilder:
(context, class2_index) {
return ExpansionTile(
initiallyExpanded: false,
title: Text('expansion tile 2'),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder:
(context, index3) {
return ListTile(
title:
Text('List tile'),
);
})
],
);
});
})
],
)
: Text('no data');
});
}),
ElevatedButton(
onPressed: () {
setState(() {});
},
child: Text('Set State'))
],
),
),
);
}
}
Here are the model classes:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firestore_troubleshooting/services/auth_service.dart';
class Class1 {
late var name;
late var docID;
Class1({required this.name, required this.docID});
Map<String, dynamic> toJson() => {'name': name, 'docID': docID};
Class1 fromJson(Map<String, dynamic> json) =>
Class1(name: ['name'], docID: ['docID']);
}
Future createClass1Object(name) async {
final class1_ref = FirebaseFirestore.instance
.collection('users')
.doc(AuthService().currentUser?.uid)
.collection('Class 1 Objects')
.doc();
final class1Object = Class1(name: name, docID: class1_ref.id);
final json = class1Object.toJson();
await class1_ref.set(json);
}
class2:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firestore_troubleshooting/main.dart';
import 'package:firestore_troubleshooting/services/auth_service.dart';
class Class2 {
late var name;
late var docID;
Class2({required this.name, required this.docID});
Map<String, dynamic> toJson() => {'name': name, 'docID': docID};
Class2 fromJson(Map<String, dynamic> json) =>
Class2(name: ['name'], docID: ['docID']);
}
Future createClass2Object(name, class1_index) async {
final Class2_ref = FirebaseFirestore.instance
.collection('users')
.doc(AuthService().currentUser?.uid)
.collection('Class 1 Objects')
.doc(class1Data.docs[class1_index]['docID'])
.collection('Class 2 Objects')
.doc();
final Class2Object = Class2(name: name, docID: Class2_ref.id);
final json = Class2Object.toJson();
await Class2_ref.set(json);
}
auth service:
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
User? get currentUser => _firebaseAuth.currentUser;
Future<User?> getOrCreateUser() async {
if (currentUser == null) {
await _firebaseAuth.signInAnonymously();
}
return currentUser;
}
}
Sorry, I know it's a lot of code. I'm trying to isolate the a problem I'm having in a larger project and this was the most minimal way I could recreate.

Firebase : Why appearing [clound_firestore/permission-denied] for my firestore

I know there is a lot of similar posts, but I still cannot find my own answer for my issue. Since I want to get the data from firebase without pressing the button and diretly can get the data from it, therefore I have used the StreamBuilder for my coding but I still get this error. Is this is my firestore database or realtime database permission get any wrong?
--Issue warning--
Below are my coding:
import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:profile_staff/edit_profile_page.dart';
import 'package:profile_staff/profile_widget.dart';
import 'package:profile_staff/user.dart';
import 'package:profile_staff/user_preferences.dart';
class ProfilePage extends StatefulWidget {
const ProfilePage({Key? key}) : super(key: key);
#override
_ProfilePageState createState() => _ProfilePageState();
}
class _ProfilePageState extends State<ProfilePage> {
final Stream<QuerySnapshot> users =
FirebaseFirestore.instance.collection('users').snapshots();
TextEditingController _controller = TextEditingController();
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
final user = UserPreferences.myUser;
return Scaffold(
appBar: AppBar(
leading: new IconButton(
onPressed: () {}, icon: new Icon(Icons.arrow_back_ios_sharp)),
title: Center(
child: Text(
'My Profile',
style: TextStyle(color: Colors.white),
),
),
actions: [
IconButton(
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => EditProfilePage()),
);
},
icon: new Icon(Icons.create_outlined))
],
backgroundColor: Colors.green,
shadowColor: Colors.white,
elevation: 3,
),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Read Data',
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w600),
),
Container(
height: 250,
padding: const EdgeInsets.symmetric(vertical: 20),
child: StreamBuilder<QuerySnapshot>(
stream: users,
builder: (
BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot,
) {
// if (!snapshot.hasData) {
// return Text('error404');
// }
if (snapshot.connectionState == ConnectionState.waiting) {
return Text('Loading');
}
final data = snapshot.requireData;
return ListView.builder(
itemCount: data.size,
itemBuilder: (context, index) {
return Text(
'My name is ${data.docs[index]['name']} and I am ${data.docs[index]['age']}');
},
);
},
))
],
),
}
My Firestore Database:
My Realtime Database:
enter image description here
enter image description here
I was facing same issue.Forgot to deploy/upload new rules

how to retrieve a list from a document in firebase flutter?

i want to retrieve a list inside a document and show it through a listview.builder
Cart:[ 0 "default", 1 "bugatti chiron", 2 "examp" 3 "bugatti veron", 4 "examp", 5 "bugatti chiron 20" ]
so the above array is what i want to retrieve and show in a listview.
and the class below is how i tried to implement it but failed
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class cart extends StatefulWidget {
#override
_cartState createState() => _cartState();
}
class _cartState extends State<cart> {
FirebaseAuth auth = FirebaseAuth.instance;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: StreamBuilder<QuerySnapshot>(
stream: FirebaseFirestore.instance.collection('user').snapshots(),
builder: (context, snapshot) {
return Column(children: [
snapshot.hasData
? Expanded(
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Column(children: [
InkWell(
onTap: () {},
child: Card(
child: Text(snapshot.data!.docs[index][Cart]),
)),
]);
},
itemCount: snapshot.data!.docs.length,
))
: Center(
child: CupertinoActivityIndicator(),
),
TextButton(
child: Text('checkout'),
onPressed: () {
FirebaseFirestore.instance
.collection('user')
.doc(auth.currentUser!.uid);
})
]);
},
),
);
}
}
Use get(), to get a specific field in your user map, like this:
child: Text(snapshot.data!.docs[index].get('Cart'),

Flutter: Firebase storage download url

I am new to Flutter and I am trying to make a wallpaper app where I use Firebase to store my images. The app retrieves images from Firebase and the user can share and download the images to the device. I'm using image_gallery_saver package but I wasn't able to get the url of the images so I can add it to the image_gallery_saver function, is there a simple way to get the url of an image from firebase after the user clicks on a specific image?
The following is the home page:
import 'package:cardstest2/Screens/ImageScreen.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:async';
class FirestoreListViewPage extends StatefulWidget {
#override
_FirestoreListViewPageState createState() => _FirestoreListViewPageState();
}
class _FirestoreListViewPageState extends State<FirestoreListViewPage> {
Future _data;
Future getPosts() async {
var firestore = Firestore.instance;
QuerySnapshot qn = await firestore.collection("gallery").getDocuments();
return qn.documents;
}
#override
void initState() {
super.initState();
_data = getPosts();
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: Text('Subcategories'),
),
body: Container(
child: FutureBuilder(
future: _data,
builder: (_, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Center(
child: Text('Waiting...'),
);
} else {
return ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (_, index){
return Card(
child: ListTile(
title: Image.network(snapshot.data[index].data['GalleryUrl']),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => imageScreenPage(snapshot.data[index].data['GalleryUrl']),
),
);
},
),
);
});
}
}),
),
);
}
}
The following is the imageScreen page:
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:share/share.dart';
import 'package:dio/dio.dart';
import 'package:image_gallery_saver/image_gallery_saver.dart';
import 'dart:ui';
class imageScreenPage extends StatefulWidget {
String cardPath;
imageScreenPage(this.cardPath);
#override
_imageScreenPageState createState() => _imageScreenPageState();
}
class _imageScreenPageState extends State<imageScreenPage> {
final LinearGradient backgroundGradient = new LinearGradient(
colors: [new Color(0x10000000), new Color(0x30000000)],
begin: Alignment.topLeft,
end: Alignment.bottomRight);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: new SizedBox.expand(
child: new Container(
decoration: new BoxDecoration(gradient: backgroundGradient),
child: new Stack(
children: <Widget>[
new Align(
alignment: Alignment.center,
child: new Hero(
tag: widget.cardPath,
child: new Image.network(widget.cardPath),
),
),
new Align(
alignment: Alignment.topCenter,
child: new Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
new AppBar(
elevation: 0.0,
backgroundColor: Colors.transparent,
leading: new IconButton(
icon: new Icon(
Icons.close,
color: Colors.black,
),
onPressed: () => Navigator.of(context).pop()),
)
],
),
),
],
),
),
),
persistentFooterButtons: <Widget>[
IconButton(
icon: Icon(Icons.wallpaper), onPressed: () {},
),
IconButton(
icon: Icon(Icons.file_download), onPressed: () {_save();},
),
IconButton(
icon: Icon(Icons.share), onPressed: () {Share.share(widget.cardPath);},
),
],
);
}
_save() async {
var response = await Dio().get("<insert url>", options: Options(responseType: ResponseType.bytes));
final result = await ImageGallerySaver.saveImage(Uint8List.fromList(response.data));
print(result);
}
}
To get the downloadUrl, then do the following:
StorageTaskSnapshot snapshot = await storage
.ref()
.child("images/$imageName")
.putFile(file)
.onComplete;
if (snapshot.error == null) {
final String downloadUrl =
await snapshot.ref.getDownloadURL();
}
use putFile to add the file to Firebase Storage, then you can use snapshot.ref.getDownloadURL() to get the url.
For all the people using flutter in 2021
This worked for me
import 'package:firebase_storage/firebase_storage.dart' as firebase_storage;
Future<String> uploadImage(imageFile) async {
firebase_storage.Reference ref = storage.ref().child('post_$postId.jpg');
firebase_storage.UploadTask uploadTask = ref.putFile(imageFile);
print('File Uploaded');
var imageUrl = await (await uploadTask).ref.getDownloadURL();
String url = imageUrl.toString();
return url;
}
uploadImage() is a function which takes in an imageFile
You have to call it using await uploadImage(imageFile) inside an asynchronous function

Flutter Navigator push data from firebase

We are trying to get data from firebase which we have currently being rendered within a grid view, but I want to be able to click on the item within the grid view and read more about it.
This is what I have so far and the error I am getting in VS
The argument type 'DocumentSnapshot' can't be assigned to the parameter type 'Merchant'.
HomeScreen
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'dart:async';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:paylaterapp/screens/GridMerchantDetails.dart';
Future<void> main() async {
final FirebaseApp app = await FirebaseApp.configure(
name: 'BNPL',
options: const FirebaseOptions(
googleAppID: '***',
gcmSenderID: '***',
apiKey: '***',
projectID: '***',
),
);
final Firestore firestore = Firestore(app: app);
await firestore.settings(timestampsInSnapshotsEnabled: true);
}
class HomeScreen extends StatelessWidget {
HomeScreen(this.firestore);
final Firestore firestore;
CollectionReference get merchants => firestore.collection("merchants");
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Stores'),
),
body: _gridView(),
);
}
Widget _gridView() {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('merchants').orderBy('name', descending: false).snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int merchantCount = snapshot.data.documents.length;
return GridView.builder(
scrollDirection: Axis.vertical,
itemCount: merchantCount,
gridDelegate:
new SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2),
itemBuilder: (_, int index) {
final DocumentSnapshot document = snapshot.data.documents[index];
final dynamic logo = document['logo_url'], mainImage = document['main_image_url'];
return
CupertinoButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => GridMerchantDetails(document),
),
);
},
child: (
Container(
height: 300,
width: 300,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
color: Colors.grey,
image: DecorationImage(
image: new NetworkImage(mainImage != null ? mainImage.toString() : 'https://images.unsplash.com/photo-1446844805183-9f5af45f89ee',
)
)
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Image.network(logo != null ? logo.toString() : 'https://images.unsplash.com/photo-1446844805183-9f5af45f89ee',
width: 220,
fit: BoxFit.fill,
)
]
)
)
)
);
},
);
},
);
}
}
class GridMerchantDetails extends StatelessWidget {
final Merchant merchant;
GridMerchantDetails(this.merchant);
#override
Widget build(BuildContext context) {
return Scaffold(
primary: true,
appBar: AppBar(
title: Text(merchant.name),
),
backgroundColor: Colors.deepPurpleAccent,
body: ListView(
children: <Widget>[
HeaderBanner(this.merchant),
Container(
padding: const EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 20.0),
child: Text(
merchant.desc,
style: TextStyle(
fontSize: 13.0,
color: Colors.white,
),
),
),
],
),
);
}
}

Resources