Kristina
Kristina

Reputation: 129

Add data instead of overwriting it

When I use pop up AddPlanScreen to add a note to the widget, it overwrites the document instead of adding it. Registering, logging and setting data work properly.

What I've tried to do:

  1. Using FirebaseFirestore.instance.runTransaction but I couldn't use + operator for String as I add data to map.
  2. set(..., SetOptions(merge:true))
  3. update method Do I have to try to create a new Map and add data there? I am new to programming and will be very grateful for any suggestions.

This is a method I use to set and fetch data


import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';

class MyProvider extends ChangeNotifier {
  Map<String, dynamic> _names = {};

  String name(String key) => _names[key];

  void setName(String key, String newString) {
    _names[key] = newString;
    var firebaseUser = FirebaseAuth.instance.currentUser;
    FirebaseFirestore.instance
        .collection('Notes')
        .doc(firebaseUser.uid)
        .set(_names);
  }


  void fetchData() {
    var firebaseUser = FirebaseAuth.instance.currentUser;
    FirebaseFirestore.instance
        .collection('Notes')
        .doc(firebaseUser.uid)
        .get()
        .then((DocumentSnapshot documentSnapshot) {
      if (documentSnapshot.exists) {
        var data = documentSnapshot.data();
        _names = data;
      } else {
        print('The document does not exist on the database');
      }
    });
  }
}

This is Planner Screen where I show all the notes


import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:my_planner_app/widgets/my_provider.dart';
import 'file:///C:/Users/krisk/AndroidStudioProjects/planner_app/lib/widgets/weekday_card.dart';
import 'package:provider/provider.dart';

class PlannerScreen extends StatefulWidget {
  static const String id = 'planner_screen';

  @override
  _PlannerScreenState createState() => _PlannerScreenState();
}

class _PlannerScreenState extends State<PlannerScreen> {

  Widget build(BuildContext context) {
    Provider.of<MyProvider>(context, listen: false)
        .fetchData();
    var size = MediaQuery.of(context).size;

    final double itemHeight = (size.height - 24) / 2;
    final double itemWidth = size.width / 2;
    return Scaffold(
      backgroundColor: Color(0xFFcf9e9f),
      body: Container(
        child: GridView(
          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
            crossAxisCount: 3,
            childAspectRatio: (itemWidth / itemHeight),
          ),
          children: <Widget>[
            WeekDayCard(
              text: '',
            ),
            WeekDayCard(text: 'Monday' ),
            WeekDayCard(text: 'Tuesday'),
            WeekDayCard(text: 'Wednesday'),
            WeekDayCard(text: 'Thursday'),
            WeekDayCard(text: 'Friday'),
            WeekDayCard(text: 'Saturday'),
            WeekDayCard(text: 'Sunday'),
            WeekDayCard(text: 'Notes'),
          ],
        ),
      ),
    );
  }
}

This is associated WeekDayCard widget


import 'package:flutter/material.dart';
import 'package:my_planner_app/screens/addPlan_screen.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';

class WeekDayCard extends StatefulWidget {
  WeekDayCard({@required this.text, this.name});
  final String name;
  final String text;

  @override
  _WeekDayCardState createState() => _WeekDayCardState();
}

class _WeekDayCardState extends State<WeekDayCard> {
  @override


  Widget build(BuildContext context) {
    return Consumer<MyProvider>(builder: (context, myProvider, child) {
      return Card(
        color: Color(0xFFFEEFCD),
        elevation: 10,
        child: Column(
          children: [
            Text(widget.text),
            Text(Provider.of<MyProvider>(context).name(widget.text) ?? ''
    ),
            Expanded(
              child: InkWell(
                onTap: () {
                  showModalBottomSheet(
                    backgroundColor: Color(0xFFFEEFCD),
                    context: context,
                    builder: (context) => AddPlanScreen(weekdayName: widget.text),
                  );
                },
              ),
            ),
          ],
        ),
      );
    });
  }
}

This is associated AddPlanScreen


import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:my_planner_app/widgets/my_provider.dart';

class AddPlanScreen extends StatefulWidget {
  final String weekdayName;
  const AddPlanScreen({Key key, this.weekdayName}) : super(key: key);

  @override
  _AddPlanScreenState createState() => _AddPlanScreenState();
}

class _AddPlanScreenState extends State<AddPlanScreen> {
  String name;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Expanded(
          child: TextFormField(
            onChanged: (text) {
              name = text;
            },
            decoration: InputDecoration(
              border: InputBorder.none,
            ),
            minLines: 10,
            maxLines: 30,
            autocorrect: false,
          ),
        ),
        FlatButton(
          onPressed: () {
            Provider.of<MyProvider>(context, listen: false)
                .setName(widget.weekdayName, name);
            Navigator.pop(context);
          },
          color: Colors.blue,
        ),
      ],
    );
  }
}

Upvotes: 2

Views: 294

Answers (1)

Huthaifa Muayyad
Huthaifa Muayyad

Reputation: 12353

  • You should use set only when you are creating a document for the first time and you want to give it a designated ID (not randomly generated by firebase). Or, a second use is when you want to deliberately write over your existing data.

  • When you want to update a document, or a single value\entry in it, you just use: collection('yourCollection').doc('yourDocID').update({"nameOfnewField": "new data"})

This update method will not overwrite your existing document,it will only add a new field called "nameOfnewField", or if that field already exists, it will write over it only.

i.e if nameOfnewField was a value that was false, when you update it, with .update({"nameOfnewField": "true"}), it becomes true but the rest of the document is not changed.

Upvotes: 1

Related Questions