0

I have being trying to update the data from/to Firebase, but i have some issue, and when i update the data, in the firestore, the fields are being set in null value. How can i fix?

he error is just ocorring in the Armas object, the rest data in AtributteData is fine.

MODEL

class AtributeData {
  final List<int> atributtes;
  final List<int> perks;
  final List<int> customPerksValue;
  final List<String> customPerksName;
  final List<Armas> armas;

  AtributeData(
      {this.atributtes,
      this.perks,
      this.customPerksName,
      this.customPerksValue,
      this.armas});
}

class Armas {
  final String modelo;
  final int numero;
  final int preco;

  Armas({this.modelo, this.numero, this.preco});
}

SCREEN WHEN I MAP THE DATA AND FUNCTION TO UPDATE DA DATA

class AtributteDataService {
  final String uid;
  AtributteDataService({this.uid});

  //Referencia para uma Coleção específica
  final CollectionReference atributteSheet =
      FirebaseFirestore.instance.collection('atributteSheet');

  Future updateAtributteData(
      {List<int> atributtes,
      List<int> perks,
      List<int> customPerksValue,
      List<String> customPerksName,
      List<Armas> armas,
      String modelo,
      int numero,
      int preco}) async {
    return await atributteSheet.doc(uid).set({
      'atributtes': atributtes,
      'perks': perks,
      'customPerksValue': customPerksValue,
      'customPerksName': customPerksName,
      'armas': [
        {
          'modelo': modelo,
          'numero': numero,
          'preco': preco,
        }
      ]
    });
  }

  // retorna um snapshot, mas mapeado para AtributteData
  AtributeData _atributteDataFromSnapshot(DocumentSnapshot snapshot) {
    return AtributeData(
        atributtes: List.from(snapshot['atributtes']),
        perks: List.from(snapshot['perks']),
        customPerksValue: List.from(snapshot['customPerksValue']),
        customPerksName: List.from(snapshot['customPerksName']),
        armas: List<Armas>.from(snapshot['armas'].map((e) {
          return new Armas(
            modelo: e["modelo"],
            numero: e["numero"],
            preco: e["preco"],
          );
        }))

        // markValue: List.from(snapshot['markValue']),
        );
  }

  //lista de todas as fichas dos usuários retornando em Stream

  //Obter Streams do Usuário (sem ser habilidades)
  Stream<AtributeData> get atributteData {
    return atributteSheet.doc(uid).snapshots().map(_atributteDataFromSnapshot);
  }
}

TRY TO FILL THE DATA

  await AtributteDataService(uid: user.uid).updateAtributteData(
    armas: [
      Armas(modelo: 'G2', numero: 3, preco: 3200),
      Armas(modelo: 'M4A1', numero: 1, preco: 6400),
      Armas(modelo: 'AK-47', numero: 5, preco: 7500),
    ],
    customPerksName: [],
    customPerksValue: [],
    atributtes: [0, 0, 0, 0, 0, 0, 0, 0, 0],
    perks: [
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
      0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
  0,
],

);

FIREBASE IMAGE: FIELDS FILLED BY NULL

1 Answer 1

3

You're using .set() without explicitly telling it to merge existing fields with the new updated ones.

To fix it, tell Firestore to merge your new data with existing ones by passing SetOptions:

return await atributteSheet.doc(uid).set({
      'atributtes': atributtes,
      'perks': perks,
      'customPerksValue': customPerksValue,
      'customPerksName': customPerksName,
      'armas': [
        {
          'modelo': modelo,
          'numero': numero,
          'preco': preco,
        }
      ]
    }, SetOptions(merge: true));

More on this is explained in details in the FlutterFire documentation.

You need to be careful when using set as, by default, it replaces all the content of your existing record with the new one. .set() is useful in cases where you want to Create a new document with custom ID instead of the auto-generated one by .add(), preferably, if your sole goal is to update some fields in an existing document, use .update() instead, and note that:

  1. .update() will fail if the document doesn't exist.
  2. .update() can be used if you have nested data so it gives better updating capabilities.

So, to add more items to an array property in Firestore, you would use .update() like this:

atributteSheet.doc(uid).update({'armas': FieldValue.arrayUnion(list)})

List items should be one of the types Firestore accepts, such as a Map or a String, so you should convert your list by mapping each item from Aramas your user-defined type, to a Map type.

Sign up to request clarification or add additional context in comments.

6 Comments

thanks for commenting, i've been stuck on this for a while. My goal is to create more then one field in the database. I try the way you showed me, but i was able to create just one field. In the end, if is possible, i want to create more fields. prnt.sc/nSh1tMjZa5ML (image from my firebase)
You want to add more items to armas array, correct?
In this case, you can use .update() like this: atributteSheet.doc(uid).update({'armas': FieldValue.arrayUnion(list)})
i'm getting this error: Error: Invalid argument (dartObject): Could not convert: Instance of 'Armas'
'armas': FieldValue.arrayUnion(armas), Then, when i call the method (using a button for exemple, or field to write the data) i'm using this code: armas: [ Armas(modelo: 'AK-47', preco: 2342, numero: 22), Armas(modelo: 'M4A1', preco: 2342, numero: 232), ],
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.