Reputation: 97
fairly new to Flutter. I'm trying to update an Array field that contains a List Map of type <String, dynamic>. The data structure I'm trying to achieve looks similar to the image below:
In order to update the "notes" field for my custom object without overwriting the entire Array, I'm using FieldValue.arrayUnion with SetOptions(merge: true)like so during a call to an update function :
notes: FieldValue.arrayUnion([
{
"date": DateTime.now(),
"notes": "some test notes",
"user": "some user name",
}
]),
The "notes" field is part of a much larger Object and is defined as being of type nullable List of type Map<String, dynamic> like so:
List<Map<String, dynamic>>? notes;
The problem is surfacing with this error:
The argument type 'FieldValue' can't be assigned to the parameter type 'List<Map<String, dynamic>>?'.
and in looking at every example I've come across it looks like the function "FieldValue.arrayUnion" will only accept a String value for the field name to update. Below is a code sample from the FireStore documentation at this link: https://cloud.google.com/firestore/docs/manage-data/add-data
// Atomically add a new region to the "regions" array field.
washingtonRef.update({
"regions": FieldValue.arrayUnion(["greater_virginia"]),
});
My question is: Is there a way to pass a field from a custom object to FieldValue.arrayUnion or is the only thing it will accept a string of the field name?
As requested, I've included the full code for this problem in the hopes it can be resolved:
This is the class definition with the 'notes' property with a Constructor
class SchedulerEvent extends ChangeNotifier {
String? key;
String? title;
String? fname;
String? lname;
DateTime? from;
DateTime? to;
List<Map<String, dynamic>>? notes;
Color? background;
bool? isAllDay;
/// CTOR
SchedulerEvent({
this.key,
this.title,
this.fname,
this.lname,
this.from,
this.to,
this.notes,
this.background,
this.isAllDay,
});
This is a Factory where I pull data from FireStore:
factory SchedulerEvent.fromFireStore(DocumentSnapshot<Map<String, dynamic>> fireStoreSnapshot) {
final data = fireStoreSnapshot.data();
return SchedulerEvent(
key: fireStoreSnapshot.id,
title: data?['title'],
fname: data?['fname'],
lname: data?['lname'],
from: data?['from']?.toDate(),
to: data?['to']?.toDate(),
notes: data?['notes'] is Iterable ? List.from(data?['notes']) : null,
background: null,
isAllDay: false,
);
}
This is where I save data back to Firestore:
Map<String, dynamic> toFireStore() {
return {
'title': title,
'fname': fname,
'lname': lname,
'from': from,
'to': to,
'notes': notes,
'background': background,
'isAllDay': isAllDay
};
}
This is where I create the events with (in this case) some hard-coded values for the notes:
await FirebaseFirestore.instance.collection('SchedulerEventCollection').add(SchedulerEvent(
title: '${_firstNameFormFieldController.text} ${_lastNameFormFieldController.text}',
fname: _firstNameFormFieldController.text,
lname: _lastNameFormFieldController.text,
from: targetEvent.from,
to: targetEvent.to,
notes: [
{
"date": DateTime.now(),
"notes": "some notes",
"user": "some user",
}
],
background: null,
isAllDay: false)
.toFireStore());
formSubmit("Submitted the entry!");
} on Exception catch (e) {
formSubmit("Error submitting your event! ${e.toString()}");
Finally, this is where the errors start to happen when I try to update. The error states
await FirebaseFirestore.instance.collection('SchedulerEventCollection').doc(targetEvent.key).set(SchedulerEvent(
title: '${_firstNameFormFieldController.text} ${_lastNameFormFieldController.text}',
fname: _firstNameFormFieldController.text,
lname: _lastNameFormFieldController.text,
from: targetEvent.from,
to: targetEvent.to,
notes: FieldValue.arrayUnion([
{
"date": DateTime.now(),
"notes": "some new notes",
"user": "some different user",
}
]),
background: null,
isAllDay: false)
.toFireStore(), SetOptions(merge: true));
formSubmit("Updated the Event!");
} on Exception catch (e) {
formSubmit("Error submitting your event! ${e.toString()}");
The error is below (I've tried multiple data types for "notes" but still the same problem.
Upvotes: 0
Views: 884
Reputation: 2835
Your toFirestore
is expecting notes
to be of type List<Map<String, dynamic>>?
, not FieldValue.arrayUnion
(and that is okay). Update your data like this:
try {
final schedulerEventJson = SchedulerEvent(
title:
'${_firstNameFormFieldController.text} ${_lastNameFormFieldController.text}',
fname: _firstNameFormFieldController.text,
lname: _lastNameFormFieldController.text,
from: targetEvent.from,
to: targetEvent.to,
// remove notes from here.
background: null,
isAllDay: false,
).toFireStore();
// here I set the value of notes directly into the json
schedulerEventJson['notes'] = FieldValue.arrayUnion([
{
"date": DateTime.now(),
"notes": "some new notes4",
"user": "some different user4",
},
]);
await FirebaseFirestore.instance
.collection('SchedulerEventCollection')
.doc(targetEvent.key)
.set(schedulerEventJson, SetOptions(merge: true));
formSubmit("Updated the Event!");
} on Exception catch (e) {
formSubmit("Error submitting your event! ${e.toString()}");
}
Upvotes: 1