Flutter document Firestore is not deleting [CLOSE] - firebase

I'm trying to delete document in firestore with this function,
[UPDATE] following code from the documentation
class DatabaseService {
final String uid;
final String taskId;
final String boardId;
DatabaseService({this.uid, this.taskId, this.boardId});
///delete task
Future<void> deleteTask() async {
return await FirebaseFirestore.instance
.collection('user')
.doc(uid)
.collection('tasks')
.doc(taskId)
.delete()
.then((value) => print('task $taskId deleted'))
.catchError((error) => print("Failed to delete task: $error"));
}
}
I put wrong collection name, supposedly tasks. I already update with the right name.
trigger button:
IconButton(
icon: Icon(
Icons.delete_outline,
color: kColorRed,
),
onPressed: () async {
print('task delete pressed');
print(widget.userId);
print(widget.taskId);
await DatabaseService(uid: widget.userId, taskId: widget.taskId)
.deleteTask();
Navigator.pop(context);
}),
output:
flutter: task delete pressed
flutter: VWtHv8LPE3brezl9a5zmHlwYM5h2
flutter: [#9bb27]
flutter: VWtHv8LPE3brezl9a5zmHlwYM5h2 task [#9bb27] deleted
inside the document:
it back with the print result. But, when I checked on Firestore, the document still there.
Am I doing it right?

I got the same problem .
I have solve this by check userid is passing or not .I mean getting the value for userid

Related

How do you delete a document by timestamp in firestore flutter?

So I am trying to make a chat app with cloud Firestore and I don't how to delete a document by timestamp.
This is currently how I delete a document.but when I tried it deletes all the document:
onLongPress: () async {
await FirebaseFirestore.instance
.collection('messages')
.doc(
groupChatId)
.collection(
groupChatId)
.orderBy("timestamp",descending: true).get().then((value) => {
for(DocumentSnapshot ds in value.docs){
ds.reference.delete()
}
});
},
try this code:
await FirebaseFirestore.instance
.collection('messages')
.doc(
groupChatId)
.collection(
groupChatId)
.where("timestamp", isLessThan: DateTime.now().microsecondsSinceEpoch-TheNumberOfMicrosencundenTheDocumentCanBeOld).get().then((value) => {
for(DocumentSnapshot ds in value.docs){
ds.reference.delete()
}
});

Flutter + Firebase Authentication - update user after updateProfile

I am trying to update user profile and then reloading it and getting back updated user.
FirebaseAuth auth = FirebaseAuth.instance;
updateDisplayName(user, displayname) async {
await user.updateProfile(displayName: displayname);
await user.reload().then((user) {
return auth.currentUser;
});
}
And then I am calling the above 'updateDisplayName' in an InkWell
InkWell(
onTap: () {
user = updateDisplayName(widget.username, displayName);
print(user);
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
MobileNumberScreen(widget.username),
));
},
child: ....
)
The print in onTap returns
flutter: Instance of 'Future'
Basically what I want is I want to update the display name and return updated user so going forward from here I have the user with updated details.

Retrieving user email from Firebase in Flutter

In my AuthProvider class where I handle my sign in, sign, out authentications, I created 2 functions that returns a Future String like so
Future<String> currentUser() async {
FirebaseUser user = await _auth.currentUser();
return user.uid;
}
Future<String> getCurrentUserEmail() async {
FirebaseUser user = await _auth.currentUser();
final String email = user.email.toString();
// print(email);
return email;
}
In my menu screen, I want to display my current signed in user email in a text field and I am calling it as below.
UserAccountsDrawerHeader(
accountName: Text('Brad Pitt'),
accountEmail: Text(
'${AuthProvider.of(context).auth.getCurrentUserEmail()}'),
I have tried using both the currenUser() and getCurrentUserEmail() to try to display the loggedIn user's email but I keep getting a "Instance of Future" displayed.
Is there something I'm overlooking here? I've tried every possible hack I can think of.
Thanks.
Since your getCurrentUserEmail returns a Future, you'll need to use a FutureBuilder to use it in your build method.
accountEmail: FutureBuilder<String>(
future: AuthProvider.of(context).auth.getCurrentUserEmail(),
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
if (snapshot.hasData) {
return Text(snapshot.data)
}
else {
return Text("Loading user data...")
}
}
)
The best thing to do is to upgrade to firebase_auth:0.18.0, after upgrade you can get the currentUser synchronously!
dependencies:
flutter:
sdk: flutter
firebase_core : ^0.5.0
firebase_auth : ^0.18.0
initialize Firebase:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Then in UsersAccountDrawerHeader:
UserAccountsDrawerHeader(
accountName: Text('Brad Pitt'),
accountEmail: Text('${auth.instance.currentUser.email}'),
Also check:
Undefined class 'FirebaseUser'
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase
Retrieving user email, null safety supported.
var currentUser = FirebaseAuth.instance.currentUser;
Text('admin email: ${FirebaseAuth.instance.currentUser!.email}'),
You need to add ~await~ in front of the function as it's a function that returns a ~Future~
await AuthProvider.of(context).auth.getCurrentUserEmail()
After initilizing your Firebase in your main
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
Now in the Text widget to display the current user's email use
Text('${FirebaseAuth.instance.currentUser!.email}',),

"The operator '[]' isn't defined" error when using .data[] in flutter firestore

I am learning to use firestore in flutter following Net Ninja's tutorial on youtube. After user authenticatin was done this guy added user records to the database whenever a new user is created, for doing this a new model was added passing 1 String named "name" and from what I undertstood for calling that he mapped the model and then used .data['name'] to get that string from the model(string was called name) and when doing this, I got the error The operator '[]' isn't defined for the type 'Map<String, dynamic> Function()' Why am I getting this error?
username model
class Username {
final String name;
Username({ this.name });
}
databse.dart file (the following code is wrapped in a class called DatabaseService)
List<Username> _usernameListFromSnapshot(QuerySnapshot snapshot) {
return snapshot.docs.map((doc){
return Username(
name: doc.data['name'] ?? '',
);
}).toList();
}
auth.dart
Future registerWithEmailAndPassword(String email, String password) async {
try {
UserCredential result = await _auth.createUserWithEmailAndPassword(email: email, password: password);
User user = result.user;
// create a new document for the user with uid
await DatabaseService(uid: user.uid).updateUserData('user123');
return _userFromFirebaseUser(user);
} catch(e) {
print(e.toString());
return null;
}
}
if you have any questions or need to see more code, please let me know in the comments
Change this:
name: doc.data['name'] ?? ''
Into this:
name: doc.data()['name'] ?? ''
data() is a method now therefore you have to add (), from the source code:
Map<String, dynamic> data() {
return _CodecUtility.replaceDelegatesWithValueInMap(
_delegate.data(), _firestore);
}
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/cloud_firestore/cloud_firestore/lib/src/document_snapshot.dart#L38
For me, worked like this:
return snapshot.docs.map((doc) {
return Todo(
// before
title: doc.data()['title'],
// after
title: (doc.data() as dynamic)['title'],
);
}).toList();
In pubspec.yaml:
environment:
sdk: ">=2.12.0 <3.0.0"
...
cloud_firestore: ^2.3.0
firebase_core: ^1.3.0
Firestore's data used to be a property of QueryDocumentSnapshot, but now it is a function, data().
And, as the error message suggests, what you are dealing with is indeed a Map<String, dynamic> Function(), i.e. a function that returns a map.
So, simply add empty parentheses to call the function data:
doc.data()['name']
messageText = message['text'];
This syntax should work with any updated plugins you use.
StreamBuilder<QuerySnapshot>(
stream: _fireStore.collection('messages').snapshots(),
builder: (context, snapshot){
if(!snapshot.hasData){
return Center(
child: CircularProgressIndicator(
// ignore: missing_return
backgroundColor: Colors.lightBlueAccent,
),
);
}
final messages = snapshot.data.docs;
List<Text> messageWidgets = [];
for(var message in messages){
final messageText = message.data()['text'];
final messageSender = message.data()['sender'];
final messageWidget = Text('$messageText from $messageSender');
messageWidgets.add(messageWidget);
}
return Column(
children: messageWidgets,
);
}
),
yes, you should try message['text']

Firestore Transactions do not work

I found some issue thread with people also not being able to complete transactions, but it does not even provide solutions.
Problem
Suddenly, my transactions crashes when using transaction.get.
runTransaction(
(Transaction transaction) async {
await transaction.get(documentReference); // "Timed out waiting for Task"
}
The PlatformException does also not really help me because it crashes in platform_channel...
E/flutter (16297): [ERROR:topaz/lib/tonic/logging/dart_error.cc(16)] Unhandled exception:
E/flutter (16297): PlatformException(Error performing transaction, Timed out waiting for Task, null)
E/flutter (16297): #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:547:7)
E/flutter (16297): #1 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:279:18)
E/flutter (16297): <asynchronous suspension>
E/flutter (16297): #2 Firestore.runTransaction (file:///G:/flutter/.pub-cache/hosted/pub.dartlang.org/cloud_firestore-0.7.3/lib/src/firestore.dart:115:10)
// here comes another <asynchronous suspension> followed by my code
This comes from Android.
This Error comes sometimes because:
don't debug the transaction while it's running, so put the breakpoint in a proper line before or after.
Another errors come because you don't :
do all get calls first, then your write or update comes.
as Firestore document said:
"Read operations must come before write operations."
https://firebase.google.com/docs/firestore/manage-data/transactions#transactions
The issue I was having has since been fixed by the cloud_firestore team.
If you are still experiencing a similar issue, you should either ask a question here on StackOverflow or create an issue.
Note: You can also make atomic changes to data using transactions.
While this is a bit heavy-handed for incrementing a vote total, it is
the right approach for more complex changes. Here is what a
transaction that updated the votes count might look like.
onTap: () => Firestore.instance.runTransaction((transaction) async {
final freshSnapshot = await transaction.get(record.reference);
final fresh = Record.fromSnapshot(freshSnapshot);
await transaction
.update(record.reference, {'votes': fresh.votes + 1});
}),
How does this work? By wrapping the read and write operations in one
transaction, you're telling Cloud Firestore to only commit a change if
there was no external change to the underlying data while the
transaction was running. If two users aren't concurrently voting on
that particular name, the transaction runs exactly once. But if the
number of votes changes between the transaction.get(...) and the
transaction.update(...) calls, the current run isn't committed, and
the transaction is retried. After 5 failed retries, the transaction
fails.
Source
https://codelabs.developers.google.com/codelabs/flutter-firebase/index.html#10
This works without any problems:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
Future<void> main() async {
final FirebaseApp app = await FirebaseApp.configure(
name: 'yourappname',
options: const FirebaseOptions(
googleAppID: 'yourgoogleid',
gcmSenderID: 'yourgmssenderid',
apiKey: 'yourapikey',
projectID: 'yourprojectid',
),
);
final Firestore firestore = Firestore(app: app);
await firestore.settings(
timestampsInSnapshotsEnabled: true,
persistenceEnabled: true,
sslEnabled: true
);
runApp(MaterialApp(
title: 'Firestore Example', home: MyHomePage(firestore: firestore)));
}
class MessageList extends StatelessWidget {
MessageList({this.firestore});
final Firestore firestore;
#override
Widget build(BuildContext context) {
return StreamBuilder<QuerySnapshot>(
stream: firestore.collection('messages').snapshots(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (!snapshot.hasData) return const Text('Loading...');
final int messageCount = snapshot.data.documents.length;
return ListView.builder(
itemCount: messageCount,
itemBuilder: (_, int index) {
final DocumentSnapshot document = snapshot.data.documents[index];
return ListTile(
title: Text(document['message'] ?? '<No message retrieved>'),
subtitle: Text('Message ${index + 1} of $messageCount'),
);
},
);
},
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({this.firestore});
final Firestore firestore;
CollectionReference get messages => firestore.collection('messages');
Future<void> _addMessage() async {
final DocumentReference postRef = firestore.document('posts/123');
firestore.runTransaction((Transaction tx) async {
DocumentSnapshot postSnapshot = await tx.get(postRef);
if (postSnapshot.exists) {
await tx.update(postRef, <String, dynamic>{'likesCount': postSnapshot.data['likesCount'] + 1});
}
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Firestore Example'),
),
body: MessageList(firestore: firestore),
floatingActionButton: FloatingActionButton(
onPressed: _addMessage,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}

Resources