I've got an error while i tried to add value to value from firestore.
I want to sum value from kcal variable with firestore "progress" value
progressAdd = nutr + kcal2;
Error screenshot
Future addMeal() async {
var nutr;
await FirebaseFirestore.instance
.collection('usersData')
.doc(FirebaseAuth.instance.currentUser!.uid)
.get()
.then((doc) => {nutr = doc.data()});
print('test');
if (nutr != null) {
this.progress = nutr['progress'];
setState(() {
progressAdd = nutr + kcal2;
FirebaseFirestore.instance
.collection('usersData')
.doc(FirebaseAuth.instance.currentUser!.uid)
.update({'progress': progressAdd});
});
} else {
print('test2');
return showDialog(
context: context,
builder: (context) {
return AlertDialog(
backgroundColor: mainFontColor().tsubColor,
title: Text(
':/',
textAlign: TextAlign.center,
style: GoogleFonts.lato(
fontWeight: FontWeight.w600, color: Colors.white),
),
content: Container(
height: 120,
width: 250,
child: Column(children: [
Text(
'Something went wrong!',
style: GoogleFonts.dosis(color: Colors.white),
),
SizedBox(
height: 5,
),
Text(
'Go back and try again!',
style: GoogleFonts.dosis(color: Colors.white),
),
SizedBox(
height: 20,
),
Container(
height: 40,
width: 180,
child: ElevatedButton(
child: Text('OK'),
style: ElevatedButton.styleFrom(
backgroundColor: mainFontColor().tsubColor2),
onPressed: (() => Navigator.pop(context))),
)
]),
),
);
});
}
}
This line:
.then((doc) => {nutr = doc.data()});
will assign the doc.data() which have a type of Map<String, dynamic> to the nutr variable.
so, this:
progressAdd = nutr + kcal2;
is actually not valid, because you want to make an addition over objects that can't be summed, nutr have a type of Map<String, dynamic> and kcal2 is double.
from the code I read, I assume that you want to get the existing progress on the Firestore document and update it with the sum of it + kcal2, so try the following:
instead of:
progressAdd = nutr + kcal2;
replace with this:
progressAdd = this.progress + kcal2;
this now should be valid that you want to sum to numbers the update in Firestore.
Related
here are my function name fetchPrayerData() and inside the function i want to count the data how many subuh that are "Prayed On Time, "Prayed Late", and "Not Prayed" and display the data in the pie chart but, unfortunately the data count won't display in the pie chart although there is no error in the code.
Future<List<PieChartSectionData>> fetchPrayerData() async {
double subuhPrayed = 0;
double subuhPrayedLate = 0;
double subuhNotPrayed = 0;
// subuhPrayed = prayedOnTimeQuerySnapshot.docs.length.toDouble();
// subuhPrayedLate = prayedLateQuerySnapshot.docs.length.toDouble();
// subuhNotPrayed = notPrayedQuerySnapshot.docs.length.toDouble();
FirebaseFirestore.instance
.collection('record_prayer')
.where('prayerName', isEqualTo: 'subuh')
.where('dailyPrayerStatus', isEqualTo: 'Prayed On Time')
.count()
.get()
.then((querySnapshot) => subuhPrayed = querySnapshot.count.toDouble());
FirebaseFirestore.instance
.collection('record_prayer')
.where('prayerName', isEqualTo: 'subuh')
.where('dailyPrayerStatus', isEqualTo: 'Prayed Late')
.count()
.get()
.then(
(querySnapshot) => subuhPrayedLate = querySnapshot.count.toDouble());
FirebaseFirestore.instance
.collection('record_prayer')
.where('prayerName', isEqualTo: 'subuh')
.where('dailyPrayerStatus', isEqualTo: 'Not Prayed')
.count()
.get()
.then((querySnapshot) => subuhNotPrayed = querySnapshot.count.toDouble());
return [
PieChartSectionData(
color: Colors.green,
value: subuhPrayed,
//title: '$prayedOnTimeQuerySnapshot',
title: '${(subuhPrayed * 100).toStringAsFixed(0)}%',
radius: 60,
titleStyle: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
PieChartSectionData(
color: Colors.yellow,
value: subuhPrayedLate,
//title: '',
title: '${(subuhPrayedLate * 100).toStringAsFixed(0)}%',
radius: 60,
titleStyle: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
PieChartSectionData(
color: Colors.red,
value: subuhNotPrayed,
title: '${(subuhNotPrayed * 100).toStringAsFixed(0)}%',
radius: 60,
titleStyle: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.black,
),
),
];
}
here are the stateful widget that i want to display the data in the pie chart but, it wont display the data that count from the function.
Expanded(
child: FutureBuilder<
List<PieChartSectionData>>(
future: fetchPrayerData(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.data != null) {
return AspectRatio(
aspectRatio: 1,
child: PieChart(
PieChartData(
pieTouchData: PieTouchData(
touchCallback: (FlTouchEvent
event,
pieTouchResponse) {},
),
borderData: FlBorderData(
//show: false;
),
sectionsSpace: 0,
centerSpaceRadius: 40,
sections: snapshot.data!,
),
),
);
}
return const CircularProgressIndicator();
},
),
),
I recently made a button, and I'm wondering how to include a message that says "success" after the button is pressed and data is stored in the firebase.
The button functions as intended and all data is stored in Firebase, as can be seen in the code, but I would want to have a message inside the button or on the screen informing the user that the data has been uploaded successfully.
code -
Container(
height: 60,
width: 290,
padding: EdgeInsets.all(10),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
textStyle: TextStyle(fontSize: 24),
minimumSize: Size.fromHeight(24),
shape: StadiumBorder()),
child: isLoading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
CircularProgressIndicator(
color: Colors.white),
SizedBox(width: 10),
Text('Please wait'),
])
: Text(
'Submit',
style: TextStyle(fontSize: 21),
),
onPressed: () async {
Map<String, dynamic> data = {
'Other medication':
_othermedicationController.text,
'Preventer inhaler': _preventController.text,
'Reliever inhaler': _relieverController.text,
'Triggers': _triggersController.text +
(', ') +
_triggersController2.text
};
if (isLoading) return;
FirebaseFirestore.instance
.collection('user')
.doc()
.collection('Medication')
.add(data);
setState(() => isLoading = true);
await Future.delayed(Duration(seconds: 2));
setState(() => isLoading = false);
},
),
),
thank you
you have to make a seperate bool function with a try catch then return true if success else false and reflect the ui accordingly to return value ... some thing like as following : -
Container(
height: 60,
width: 290,
padding: EdgeInsets.all(10),
child: ElevatedButton(
style: ElevatedButton.styleFrom(
textStyle: TextStyle(fontSize: 24),
minimumSize: Size.fromHeight(24),
shape: StadiumBorder()),
child: isLoading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
CircularProgressIndicator(
color: Colors.white),
SizedBox(width: 10),
Text('Please wait'),
])
: Text(
'Submit',
style: TextStyle(fontSize: 21),
),
onPressed: () async {
Map<String, dynamic> data = {
'Other medication':
_othermedicationController.text,
'Preventer inhaler': _preventController.text,
'Reliever inhaler': _relieverController.text,
'Triggers': _triggersController.text +
(', ') +
_triggersController2.text
};
if (isLoading) return;
final success = await getData();
if(success) {print('success');}
//show toast or something
},
),
),
Future<bool>getData()async{
bool success = false;
try {
await FirebaseFirestore.instance
.collection('user')
.doc()
.collection('Medication')
.add(data);
setState(() => isLoading = true);
success = true;
}catch(e){
success = false ;
setState(() => isLoading = false;
print(e);
}
return success;
}
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.
I was trying to calculate the percentage by retrieving the required field values from the firestore using FutureBuilder, while doing so I'm facing this error. Can someone please let me know the reason of this error and where I'm going doing wrong in the code. Please help me in solving this issue.
Here is the code :
displayPercentage() :
dynamic percentage = 0.0;
displayPercentage() async {
var totalClassesTook;
var totalClassesAttended;
try {
totalClassesTook =
await tutor_details.doc(uid).snapshots().map((event) async {
var val = await event.data()['TotalClassesTook'];
return val;
});
totalClassesTook = await totalClassesTook == null ? 0 : totalClassesTook;
totalClassesAttended =
await tutor_details.doc(uid).snapshots().map((event) async {
var val = await event.data()['TotalClassesAttended'];
return val;
});
totalClassesAttended =
await totalClassesAttended == null ? 0 : totalClassesAttended;
return percentage =
await ((totalClassesAttended / totalClassesTook) * 100) / 100;
} catch (e) {
return percentage = 0.0;
}
}
Calling the above function in the body from here :
body: Center(
child: Padding(
padding: EdgeInsets.symmetric(vertical: 150.0),
child: FutureBuilder(
future: displayPercentage(),
builder: (context, snapshot) {
return new CircularPercentIndicator(
radius: 120.0,
lineWidth: 13.0,
animation: true,
percent: snapshot.data,
center: new Text(
"${snapshot.data}",
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 20.0),
),
footer: Padding(
padding: EdgeInsets.symmetric(
horizontal: 10.0, vertical: 10.0),
child: new Text(
"Attendance Percentage",
style: new TextStyle(
fontWeight: FontWeight.bold, fontSize: 17.0),
),
),
circularStrokeCap: CircularStrokeCap.round,
progressColor: Colors.purple,
);
}),
),
),
Output
======== Exception caught by widgets library ===========================
The following NoSuchMethodError was thrown building FutureBuilder(dirty, state: _FutureBuilderState#bfce6):
The method '<' was called on null.
Receiver: null
Tried calling: <(0.0)
In builder put an if condition to check snapshot.hasData.
builder: (context, snapshot) {
if (snapshot.hasData) {
// return CircularPercentIndicator here.
},
return Text('No Data');
},
I have a Future function "_doSearch" which fetch data from server and it is working fine.
But when I add a another function inside it to display progress dialog while fetching data from the server the progress dialog is displayed but the Future function stop fetching data!!!
Any body can help ?
Future<List<Property>> _doSearch () async{
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context){
return MyProgressDialog("Please wait...");
}
);
Response response = await get("https://www.example.com/services/?action=search");
if(response.statusCode == 200){
Navigator.pop(context);
var jsonData = json.decode(response.body);
var res = jsonData["results"];
List<Property> results = [];
for (var p in res){
Property unit = Property(p["property_title"], p["property_image"]);
results.add(unit);
}
print(results.length);
return results;
}else{
Navigator.pop(context);
}
}
Use this method
static progressDialog(bool isLoading, BuildContext context) {
AlertDialog dialog = new AlertDialog(
content: new Container(
height: 40.0,
child: new Center(
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new CircularProgressIndicator(),
Padding(padding: EdgeInsets.only(left: 15.0)),
new Text("Please wait")
],
),
)),
contentPadding: EdgeInsets.fromLTRB(15.0, 15.0, 15.0, 15.0),
);
if (!isLoading) {
Navigator.of(context, rootNavigator: true).pop();
} else {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return WillPopScope(onWillPop: () {}, child: dialog);
},
useRootNavigator: true,
);
}
}
example:
Constants.progressDialog(true, context);
Response response = await get("https://www.example.com/services/?action=search");
Constants.progressDialog(false, context);
if(response.statusCode == 200){
var jsonData = json.decode(response.body);
var res = jsonData["results"];
List<Property> results = [];
for (var p in res){
Property unit = Property(p["property_title"], p["property_image"]);
results.add(unit);
}
print(results.length);
return results;
}
You are killing the function using return MyProgressDialog("Please wait...");
Modify the code like this
Future<List<Property>> _doSearch () async{
pr = ProgressDialog(context,type: ProgressDialogType.Normal, isDismissible: false);
pr.style(
message: 'Please wait...',
borderRadius: 10.0,
backgroundColor: Colors.white,
progressWidget: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(Colors.orange),),
elevation: 10.0,
insetAnimCurve: Curves.easeInOut,
progressTextStyle: TextStyle(
color: Colors.black, fontSize: 13.0, fontWeight: FontWeight.w400),
messageTextStyle: TextStyle(
color: Colors.black, fontSize: 19.0, fontWeight: FontWeight.w600)
);
await pr.show();
Response response = await get("https://www.example.com/services/?action=search");
if(response.statusCode == 200){
Navigator.pop(context);
var jsonData = json.decode(response.body);
var res = jsonData["results"];
List<Property> results = [];
for (var p in res){
Property unit = Property(p["property_title"], p["property_image"]);
results.add(unit);
}
print(results.length);
pr.hide();
return results;
}else{
pr = ProgressDialog(context,type: ProgressDialogType.Normal, isDismissible: false);
pr.style(
message: 'Please wait...',
borderRadius: 10.0,
backgroundColor: Colors.white,
progressWidget: CircularProgressIndicator(valueColor: new AlwaysStoppedAnimation<Color>(Colors.orange),),
elevation: 10.0,
insetAnimCurve: Curves.easeInOut,
progressTextStyle: TextStyle(
color: Colors.black, fontSize: 13.0, fontWeight: FontWeight.w400),
messageTextStyle: TextStyle(
color: Colors.black, fontSize: 19.0, fontWeight: FontWeight.w600)
);
await pr.show();
Navigator.pop(context);
}
}
Do remember to add and import progress_dialog