Home > Mobile >  How to add a subcollection in a users document that has been created in Firestore with flutter
How to add a subcollection in a users document that has been created in Firestore with flutter

Time:03-29

I want to create a subcollection inside already existing users document, the subcollection will be name "collection" and the collection contain collectionName and imageUrl.

Cloud Firestore flow

/users/user-doc-id/collection/collection-doc-id

my firestore

Here is my add_new_collection.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:image_picker/image_picker.dart';
import 'package:path/path.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:ukk/constants/color_constant.dart';

class AddNewCollection extends StatefulWidget {
  const AddNewCollection({Key? key}) : super(key: key);

  @override
  State<AddNewCollection> createState() => _AddNewCollectionState();
}

class _AddNewCollectionState extends State<AddNewCollection> {
  File? _image;
  final _picker = ImagePicker();
  String url = "";
  //Editing Controllers
  final collectionNameController = TextEditingController();

  Future getImageFromGallery() async {
    final pickedFile = await _picker.pickImage(source: ImageSource.gallery);
    final File image = File(pickedFile!.path);
    setState(() {
      _image = image;
    });
  }

  uploadCollection() async {
    var imageFile = FirebaseStorage.instance
        .ref()
        .child("collectionImage")
        .child(basename(_image!.path));
    UploadTask task = imageFile.putFile(_image!);
    TaskSnapshot snapshot = await task;
    //for download
    url = await snapshot.ref.getDownloadURL();
    await FirebaseFirestore.instance.collection('collection').doc().set({
      'imageUrl': url,
      'collectionName': collectionNameController.text,
    });
    print(url);
  }

  @override
  Widget build(BuildContext context) {
    final fileName =
        _image != null ? basename(_image!.path) : 'No Image Selected';

    final addNewCollection = Material(
      elevation: 5,
      borderRadius: BorderRadius.circular(50),
      child: Container(
        width: MediaQuery.of(context).size.width,
        height: 60,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(50),
          color: kGreenColor,
        ),
        child: Material(
          borderRadius: BorderRadius.circular(50),
          color: Colors.transparent,
          child: Center(
            child: MaterialButton(
              child: Text(
                "Add New Collection",
                textAlign: TextAlign.center,
                style: GoogleFonts.dongle(
                  fontSize: 28,
                  color: kWhiteColor,
                  fontWeight: FontWeight.bold,
                ),
              ),
              padding: const EdgeInsets.fromLTRB(20, 10, 20, 15),
              minWidth: MediaQuery.of(context).size.width,
              onPressed: () {
                uploadCollection();
                // Adding the name of the collection and the image to the Firebase storage and firestore,
                // then navigating to the collection_page.dart,
                // and also displaying the result on colletion_page.dart
                // with the shape of a card from card_collection.dart
              },
            ),
          ),
        ),
      ),
    );

    return GestureDetector(
      onTap: () => FocusScope.of(context).unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: Text(
            "New Collection",
            style: GoogleFonts.dongle(
              fontSize: 40,
              color: kWhiteColor,
            ),
          ),
          backgroundColor: kDarkBlue,
          elevation: 0,
          leading: IconButton(
            icon: const Icon(
              Icons.arrow_back,
              color: kWhiteColor,
            ),
            onPressed: () {
              //passing this to our root
              Navigator.of(context).pop();
            },
          ),
        ),
        body: Form(
          child: Stack(
            children: [
              SingleChildScrollView(
                child: Column(
                  children: [
                    Center(
                      child: Container(
                        padding: const EdgeInsets.symmetric(
                          horizontal: 25,
                        ),
                        width: MediaQuery.of(context).size.width,
                        height: MediaQuery.of(context).size.height,
                        decoration: const BoxDecoration(
                          image: DecorationImage(
                            image: NetworkImage(
                                "https://firebasestorage.googleapis.com/v0/b/flutterbricks-public.appspot.com/o/backgrounds/gradienta-7brhZmwXn08-unsplash.jpg?alt=media&token=ea7ee065-0bb3-4184-8baf-9188d268f075"),
                            fit: BoxFit.fill,
                          ),
                        ),
                        child: Column(
                          // mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            InkWell(
                              onTap: () {
                                getImageFromGallery();
                              },
                              child: CircleAvatar(
                                radius: 100,
                                backgroundColor: kWhiteColor,
                                backgroundImage: _image == null
                                    ? const AssetImage("")
                                    : FileImage(File(_image!.path))
                                        as ImageProvider,
                              ),
                            ),
                            const SizedBox(height: 5),
                            Text(
                              fileName,
                              style: const TextStyle(fontSize: 16),
                            ),
                            const SizedBox(height: 40),
                            const Text(
                              'Collection Name',
                              textAlign: TextAlign.center,
                              style: TextStyle(
                                fontSize: 20,
                                fontWeight: FontWeight.w500,
                              ),
                            ),
                            TextField(
                              autofocus: false,
                              controller: collectionNameController,
                              decoration: InputDecoration(
                                contentPadding:
                                    const EdgeInsets.fromLTRB(20, 15, 20, 15),
                                hintText: "Example: My Hotwheels",
                                border: OutlineInputBorder(
                                  borderRadius: BorderRadius.circular(10),
                                ),
                              ),
                            ),
                            const SizedBox(
                              height: 20,
                            ),
                            addNewCollection,
                          ],
                        ),
                      ),
                    )
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

After that I want to get the subcollection and display it as a custom card that I made

import 'package:flutter/material.dart';
import 'package:ukk/constants/color_constant.dart';

class CardCollection extends StatelessWidget {
  const CardCollection({Key? key}) : super(key: key);

  final double _borderRadius = 24.0;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: () {
        print('card pressed');
      },
      child: Container(
        height: 150,
        width: 350,
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(_borderRadius),
          gradient: LinearGradient(
            colors: const [kLightRedColor, kLightOrange],
            begin: Alignment.topLeft,
            end: Alignment.bottomRight,
          ),
          boxShadow: const [
            BoxShadow(
              color: kDarkGreyColor,
              blurRadius: 12,
              offset: Offset(0, 6),
            ),
          ],
        ),
        child: Column(
          children: [
            Positioned.fill(
              child: Row(
                children: [
                  Container(
                    margin: EdgeInsets.all(10),
                    width: 80.0,
                    height: 80.0,
                    decoration: BoxDecoration(
                      color: Colors.grey[50],
                      border: Border.all(color: Colors.transparent),
                      shape: BoxShape.rectangle,
                    ),
                    child: Image.asset(
                      'assets/images/bag_1.png',
                      width: 50,
                      height: 50,
                      fit: BoxFit.fill,
                    ),
                  ),
                  GestureDetector(
                    onTap: () {
                      print('title pressed');
                    },
                    child: Container(
                      alignment: Alignment.topCenter,
                      margin: EdgeInsets.only(left: 16),
                      child: Text(
                        'Put Your Title Here',
                        style: TextStyle(
                          color: kWhiteColor,
                          fontSize: 23,
                          fontWeight: FontWeight.bold,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
            Positioned.fill(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  SizedBox(
                    width: 10,
                  ),
                  IconButton(
                    onPressed: () {
                      print('Delete Button Pressed');
                      //write onpressed function here
                    },
                    icon: Icon(
                      Icons.delete_forever,
                      size: 30,
                      color: kWhiteColor,
                    ),
                  ),
                  IconButton(
                    onPressed: () {
                      print('Edit Button Pressed');
                      //write onpressed function here
                    },
                    icon: Icon(
                      Icons.edit,
                      size: 30,
                      color: kWhiteColor,
                    ),
                  ),
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

If you need more source code, let me know

CodePudding user response:

Given that your collection is just a reference , you might want to add its id to the document such that collectionName,imageUrl,collectionId

to simplify lets refactor your collections to this /users/user-doc-id/collection_references/collection-doc-id

- users 
   - user1
   - user2 -collection_references
                  - collection1
                  - collection2

when creating the collection you can query your collection_references and using the collectionId you can now create new collections. /users/user-doc-id/collectionId notice I used collectionid to make it unique

  • Related