0
votes

I am new to firebase and firestore and facing problem while storing TextField data in cloud firestore and performing transactions on them, and my doubt is can we perform update transaction and if the document doesn't exist then it should create and then perform transaction...

I want to achieve the Following:

  1. I want to store the current user uid and email in a document of 'X' collection.

  2. I want to perform transaction update on 'Y' (here Y is either uid/email) document of 'X' collection and also if that document for that user doesn't exist it should create one and then perform transaction and then if the user exits the textfield without pressing the save button then it should be deleted from firestore.

  3. I want to pass user's uid, title, tag, desc, etc.. as field in the doc(docID should be the email or user's uid) of that current user.

so far I am able to get user from auth class and access it in my current working class using initState() but I dont know how to get and store that uid/email to a 'X' collections document

the code for passing data to firebase is,

 Future<void> postQ() async {
    FirebaseFirestore db = FirebaseFirestore.instance;
    CollectionReference question =
        FirebaseFirestore.instance.collection('question');
    DocumentReference cUser = question.doc(_currentUser.uid);
      // in the above line I tried to get currentuser uid but that also not working and below I want to pass title,etc... in the doc of that current user with fields title, tag, desc, users uid and email and docID should be the email or user's uid....
      await db.runTransaction((transaction) async {
      String title = title_Controller.text;
      String desc = desc_Controller.text;
      String tag = tag_Controller.text;
      DocumentReference qRef = db.collection('question').doc();
      DocumentSnapshot snapshot = await transaction.get(qRef);
      // int likesCount = snapshot.data['likes'];
      await transaction.update(qRef, {
        // 'authorId': _currentUser,
        'title': title,
        'desc': desc,
        'tag': tag,
      });
    });
  }
}

but it above code throws me below message, so how can I create one before running transactions and that document should have current users uid and email as one of the field.

cannnot run transaction on not existing document

below is the working code to get constant update from textfield in terminal,

class CreateQ extends StatefulWidget {
  final User user;
  CreateQ({Key? key, required this.user}) : super(key: key);

  @override
  State<CreateQ> createState() => _CreateQState();
}

class _CreateQState extends State<CreateQ> {
  final title_Controller = TextEditingController();
  final desc_Controller = TextEditingController();
  final tag_Controller = TextEditingController();
  @override
  void initState() {
    super.initState();
    _currentUser = widget.user;
    super.initState();
    // Start listening to changes.
    title_Controller.addListener(_latestTitle);
    desc_Controller.addListener(_latestDesc);
    tag_Controller.addListener(_latestTag);
  }

  // @override
  // void dispose() {
  // Clean up the controller when the widget is removed from the widget tree.
  // This also removes the latestvalue listener.
  // title_Controller.dispose();
  // super.dispose();
  // }

  void _latestTitle() {
    print('Title text field: ${title_Controller.text}');
  }

  void _latestDesc() {
    print('Desc text field: ${desc_Controller.text}');
  }

  void _latestTag() {
    print('Tag text field: ${tag_Controller.text}');
  }

  // ignore: unused_field
  late User _currentUser;
  

  UploadTask? task;
  File? file;

  @override
  Widget build(BuildContext context) {
 body: Container(
          padding: EdgeInsets.all(32),
          child: ListView(shrinkWrap: true, children: [
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                TextField(
                  controller: title_Controller,
                  decoration: InputDecoration(
                      hintText: 'Your Title here',
                      counterText: '',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.multiline,
                  maxLines: 1,
                  maxLength: 100,
                ),
                SizedBox(height: 8),
                TextField(
                  controller: desc_Controller,
                  decoration: InputDecoration(
                      hintText:
                          'Enter Your Description here... ',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.multiline,
                  maxLines: 15,
                  maxLength: 10000,
                ),
                SizedBox(height: 8),
                TextField(
                  controller: tag_Controller,
                  decoration: InputDecoration(
                      hintText:
                          'Add up to 5 tags to describe what your question is about',
                      counterText: '',
                      border: OutlineInputBorder()),
                  keyboardType: TextInputType.text,
                  maxLines: 1,
                  maxLength: 100,
                ),  ));
  }

and I tried using set() method but that throws error It would be very helpful if anyone can give working sample of the current problem, Thank you...