I have set up a Textformfield where users can fill in their shop & Geopoint coordinates.
They then press the submit button and it updates on our Firestore collection.
The problem I am having is how to save it as Geopoint's and not a string.
SizedBox(child: ElevatedButton(
onPressed: () async {
await collectionReference.add({
'shopName': _textEditingController.text,
'address': _textEditingController2.text,
'description': _textEditingController3.text,
'thumbNail': _textEditingController4.text,
'locationCoords':_textEditingController5.GeoPoint
},);
},
chil:Text('Add Data'),
))
Geopoint there is GeoPoint object inside Firestore plugin
'locationCoords':GeoPoint(_textEditingController5.GeoPoint.latitude,_textEditingController5.GeoPoint.longitude);
Related
This question already has an answer here:
How to remove fields from a database?
(1 answer)
Closed 10 months ago.
The application displays news cards on which there is an icon that adds news to Favorites.The added news is added to the Firestore database and displayed on a separate page with a delete icon. I need that when clicking on the icon, the document with this news is deleted from the database. How can I do that?
Icon code with addition:
Widget customListTile(Article article, BuildContext context) {
final _fireStore = FirebaseFirestore.instance;
...
IconButton(onPressed: () async {
newsController.addNews(article);
_fireStore.collection('favoriteItems').add({
'name' : article.source.name,
'title': article.title,
'image': article.urlToImage,
});
},
icon: const Icon(Icons.bookmark_border)),
}
Icon code with removal:
IconButton(onPressed: () {
newsController.removeNews(article);
},
icon: const Icon(Icons.bookmark_remove))
To delete a document, we can use the runTransaction method of the Firestore.instance and use the delete method of the Transaction class.
Flutter - remove a firebase document onTap()
await Firestore.instance.runTransaction((Transaction myTransaction) async {
await myTransaction.delete(snapshot.data.documents[index].reference);
});
First Get your ID
then, run :
IconButton(onPressed: () {
CollectionReference users = FirebaseFirestore.instance.collection('favoriteItems');
Future<void> deleteItems() {
return users
.doc('itemsID')
.delete()
.then((value) => print("Items Deleted"))
.catchError((error) => print("Failed to delete Item: $error"));
}
}, icon: const Icon(Icons.bookmark_remove))
I'm having trouble validating a text form field before data is uploaded to the Firestore database. There aren't any issues with Firestore, only with the way I have written my code.
The validation is to check that the text field is not null or empty, the same as the Flutter codelab. If the text field is empty an error message should appear and the user should remain on the same page until the text field has data. Once the text field is valid the data should be saved to Firestore, a snackbar confirmation should appear on the page and the user should be navigated to a different page.
With the code I have written the user navigates to the new page and the snackbar message appears even if all of the text form fields are empty (invalid). I tried to remove extra code to make it easier to view the code. In my form I have three text fields with identical validation rules. Any help would be greatly appreciated. Thanks.
My Text Form Field:
TextFormField(
labelText: 'Trivia Game Url',
onChanged: (val) {
triviaGameImageURL = val as String;
},
controller: _triviaGameImageURLController,
validator: _triviaGameImageURLValidator,
),
Validation method:
String? _triviaGameImageURLValidator(value) {
if (value == null || value.isEmpty) {
return 'Image Url is required';
}
return null;
}
Method to update Firestore when user taps button:
Future<void> createFirestoreTriviaGame() async {
final form = _formKey.currentState;
if (form!.validate()) {
setState(() {
_isLoading = true;
});
String triviaGameID = const Uuid().v4();
Map<String, dynamic> triviaGameMap = {
FirebaseString.triviaGameID: triviaGameID,
FirebaseString.triviaGameImageURL: triviaGameImageURL,
};
await firestoreMethods
.addTriviaGameData(
triviaGameData: triviaGameMap,
triviaGameID: triviaGameID,
)
.then((value) {
setState(() {
_isLoading = false;
});
});
}
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text(SnackBarString.triviaGameCreated),
),
);
Timer(const Duration(seconds: 2), () {
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => const AddTriviaGamePage(),
),
);
});
}
In your code the snackbar and navigation is outside the if (form!.validate()) block. Simply extend this block to include everything that you want to execute only on a valid form, and display a message if validation fails.
The snackbar and navigation should happen on successful save only, after Firestore async call completes. I recommend not to mix async/await with .then, these are the same. So simple await Firestore method, put this in a try/catch block and execute snackbar and navigation on success.
You need to wrap the textfield in a form widget and assign a form key to the form widget
final GlobalKey<FormState> formKey = GlobalKey<FormState>();
Form(
key: formKey,
child: Column(
children: [
... your text fields
// validate
if (formKey.currentState!.validate()) {
using firebase realtime database with flutter, saving user details in realtime database & will be displayed in their profile page. I am able to store and get data from database, but the data does not reflect on the screen, I am trying to show the data as an initial value in the text field. How can I show data on profile page when user clicks on the profile?
getUserDetails() async {
final userProfileDetails = await FirebaseDatabase.instance
.reference()
.child("userDetails")
.child(FirebaseAuth.instance.currentUser.uid)
.once()
.then((DataSnapshot snapshot) {
setState(() {
email = snapshot.value['email'];
city = snapshot.value['city'];
state = snapshot.value['state'];
});
});
return data;
}
widget tree -
Scaffold > Column > TextFormFields
TextFormField(
initialValue: email,
onChanged: (value) {
petName = value;
},
decoration: InputDecoration(
suffixIcon: Icon(
Icons.email,
color: grey700,
),
labelText: 'Email'),
),
If you want to see live-changes from the db you meed to make use of the provider & stream principles of flutter.
In short: you are creating a stream which delivers the desired data (a stream is listening to a specific collection/document). So if some data of the stream is changed you get a notification. The notification ends up in the provider you have to wrap a widget with. Every time the stream delivers new data your wrapped widget and everything below gets rebuild.
I have created a simple home automation project with flutter and ESP32, On my App I have a bunch of buttons that will change the state of the variables inside the firestore if they are pressed or not. If pressed send True, if not false. I'm trying to make this happen but I can't seem to get it right.
Inside the onPressed is what I have tried, all of the code is inside a Stateful class:
bool pressed = false;
Random no effect code...
CustomButton(
icon: Icons.lightbulb_outline,
text: 'On',
text2: 'Lâmpada 1\nSchuma',
onPressed: () => (){
dynamic databaseReference = Firestore.instance.collection('sensores').where('Led1','==',pressed);
Firestore.instance.runTransaction((transaction) async {
await transaction.update(
documentReference, _value);
};
},
),
SizedBox(width: 30.0),
CustomButton(
icon: Icons.lightbulb_outline,
text: 'On',
text2: 'Lâmpada 2\nSchuma',
onPressed: () => (){
},
My firestore:
Second try:
CustomButton(
icon: Icons.lightbulb_outline,
text: 'On',
text2: 'Lâmpada 1\nSchuma',
onPressed: () => (){
Firestore.instance.collection("sensores").document("2KbeT....").updateData({
'Led1': true,
});
},
),
The problem, was the button formating. The code send by Uni works great.
First add firebase to your app: https://firebase.google.com/docs/flutter/setup?platform=ios
(Import Firestore)
You can simply update your data:
Firestore.instance.collection('YourCollection').document('YourDocument').updateData({
'Led1': true,
});
To Fetch your data from the server:
await Firestore.instance
.collection('YourCollection')
.document('YourDocument')
.get()
.then((DocumentSnapshot ds) {
led1 = ds["Led1"];
led2 = ds["Led2"];
led3 = ds["Led3"];
});
I would recommend using the MQTT Protocol to communicate to your ESP32 instead of storing it in firestore. Note that firestore allows you to have 20k reads and 50k writes per day so if you have devices that need more than that it would be impractical to use firestore as a communication method.
I'm using firestore to store data of my flutter application, and I made a function that creates a document in firestore automatically after the user login
Now I want the user when he fills this form , the data will be added in the same document where the user's email exists.
RaisedButton(
child: Text("Submit"),
onPressed: () {
final CollectionReference users = Firestore.instance.collection('users');
Firestore.instance
.runTransaction((Transaction transaction) async {
CollectionReference reference =
Firestore.instance.collection('users');
await reference
.add({"fullname": nameController.text, "PhoneNumber": phoneController.text, "adresse": adressController.text});
nameController.clear();
phoneController.clear();
adressController.clear();
});}
I tried this code but it adds new document.
Specify document name before updating database.
Firestore.instance
.collection('Products')
.document('Apple')
.updateData({
'price': 120,
'quantity': 15
});
Here my price and quantity data are numbers. If yours are Strings put String values there.
Best practice is to use transaction.
Make sure that document reference is a reference to a file that you wish to update.
Firestore.instance.runTransaction((transaction) async {
await transaction.update(
documentReference, data);
};
It will make sure that update happens in order in case there are many clients doing it.
In the case of a concurrent edit, Cloud Firestore runs the entire transaction again. For example, if a transaction reads documents and another client modifies any of those documents, Cloud Firestore retries the transaction. This feature ensures that the transaction runs on up-to-date and consistent data.
More info here
Try .setData({"fullname": nameController.text, "PhoneNumber": phoneController.text, "adresse": adressController.text}, merge: true).
Update 2021:
You need to update the data to add it to an existing document.
var collection = FirebaseFirestore.instance.collection('users');
collection
.doc('doc_id') // <-- Doc ID where data should be updated.
.update({'age' : 20}) // <-- New data
.then((_) => print('Updated'))
.catchError((error) => print('Update failed: $error'));