Coming from a strong relational database background, working with a NoSql database was interesting. It requires a slightly different way of thinking about how you store your data. More specifically, I felt that was when I was building our new hybrid app with Ionic framework and Firebase/Firestore database. Some of the features of our (my) new app were user authentication and everything the user creates in the app will be saved to the user’s credentials. Sounds simple huh? Actually, if I read that, it sounds super simple to me too, however when building the app, all the tutorials I found online on Ionic, Firebase/Firestore and AngularFire, didn’t quite explain what I wanted. So, in this post, I will be showing you the logic in an Ionic/Firebase app where,

  • the user can signup/login
  • make (save) notes by the userid
  • how to retrieve all the notes saved by that user

In addition to the above, almost all of the Ionic tutorials I have seen online don’t provide code samples that support their post? I don’t intend to do that here, you can find all the code for the entire project on Github in the link below.

Background

I have been working with the Ionic framework since 2015 and Firebase since 2016 but lately, I found myself in new situation, where I have to use them together, a lot. So just as any programmer would do, I did a Google/Bing (non mutually exclusive) search for the following,

  1. Crud with ionic and Firebase tutorial
  2. Firebase authentication with Ionic framework

Those were the two major themes in my search for a tutorial to help me find what I was looking for, however I couldn’t find exactly what I was looking for. The important word here is “exactly” because all the information was there, it was just scattered across so I just had to connect the dots. Now that I think about it, what was I expecting then? more “hand holding” (this is quite embarrassing). Anyway, it didn’t take me a lot of time to connect the dots and find the solution I was after. Anyway, let’s get into it and maybe start with a simple user story first,

User Story

As a mum with new born, I can write hours upon hours of stories for my little baby girl, so I want to be able to write all this at home, either on my phone or our computer. Ohh and my husband also uses the computer at home and I don’t don’t want him to see my notes.

Problem

Hmm, I will analyse that user story in another blogpost, and in this one we will just look at an aspect of the solution to that user story. The goal would be to build an Ionic app where the user can login, make (save) notes such that every time the user logs into the app, it only retrieves the notes that the user has saved.

Solution

As I said, there are a lot of good tutorials out there on the web that explain building an Ionic CRUD app that uses Firebase as it’s backend. I won’t be covering a lot of the basics of how to setup your Firebase backend and Ionic app, instead I will discuss the code that I have shared on my Github repo. Hence, here are the assumptions

  1. You know what’s a relational database!
  2. You know what Ionic framework is, it’s purpose and how to create a basic Ionic app
  3. You know about Firebase and have an idea of what AngularFire does
  4. You know how to link up Ionic and Firebase
  5. You know how to enable the email authentication mechanism with Firebase

mdt_ionic_tutorials (Github repo)

That’s the name of the Github repo that I created to highlight the solution to the problem i.e. it’s all the necessary code for a Notes app.

p.s. please keep in mind, this repo only exists to demonstrate the type of Authentication and CRUD operation mentioned above. So try not to nitpick on how optimal the code could be.

Saving the notes per userId

To register a new user, we use the createUserWithEmailAndPassword  method from the Firebase API and this is how we do it.

private userCollection: AngularFirestoreCollection<User>;
private users: Observable<User[]>
constructor(private db: AngularFirestore,
  private afAuth: AngularFireAuth) { 
  this.userCollection = db.collection<User> ('users');
  this.users = this.userCollection.snapshotChanges().pipe(
    map (actions => {
      return actions.map (a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return {id, ... data};
      })
    })
  )
}
registerUser(value) {
  return new Promise<any>((resolve, reject) => {
    this.afAuth.auth.createUserWithEmailAndPassword(value.email, value.password).then(
      res => {
        console.log("User id after reigstration = "+res.user.uid);
        let user: User = {
          email: value.email,
          id: res.user.uid,
          name: value.name
        };
        this.userCollection.doc(res.user.uid).set(user);
        resolve(res);
      }, err => {
        reject(err);
      }
    )
  })
}

Like the blog? Subscribe for updates

Have a close look at the registerUser method in the code above…. after we have successfully registered a new user, we save a record of that user in our Firestore database. 

What did I want?

I wanted that every time a user saves a note, it’s saved as part of the user record. Now, after spending years working with Java backends, ORMs and relational databases, I envisioned the solution to be something like,

User -> User Details, [Notes]

So, when you retrieve a user record from the database, you not only retrieve the user details but also all the notes created. Programatically, you have a user object, which has username, email and id string based properties and a property that’s an array of Notes that the user created. What this means is that every time a user creates a note, it will save that note under the collection of user notes. I could’t find a single tutorial online that demonstrated the above? A majority of the tutorials I came across were mutually exclusive to “How to do Firebase Authentication with Ionic” or “How to do Firebase CRUD with Ionic”. I was a little confused at first, I was thinking surely someone ought to have written this tutorial somewhere? However, I couldn’t find it, so I decided to give this solution a little thought and I did that.

The Solution I Wanted

Here’s the code from notes.service.ts from my repo

constructor(private db: AngularFirestore,
            private afAuth: AngularFireAuth,
            private authService: AuthService) {
  let currentUser = this.authService.getCurrentUser();
  if(this.afAuth.auth.currentUser) {
    let user = this.afAuth.auth.currentUser.uid;
  }

  if (currentUser) {
    this.refreshNotesCollection(currentUser.uid)
  }
}
refreshNotesCollection(userId) {
  this.notesCollection = this.db.collection('users').doc(userId).collection<Note>('notes');
    this.notes = this.notesCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return {id, ... data};
      }))
    )
}

See! The solution is really quite simple, it just requires a slightly different chain of thought. For the first hour I simply couldn’t think of the above? Then, I decided to take my hands away from the keyboard, get a cup of coffee and actually think about how Firestore saves data. Then it hit me! of course!!! it’s just a key-value pairs based database (DB), that’s all there is, storing data here is much simpler!

Like the blog? Subscribe for updates

Try to think of it this way, with Firestore we are dealing with collections and data i.e. collection => relational DB row , data => relational DB column get it? Let’s look at this bit of code,

this.db.collection('users').doc(userId).collection<Note>('notes');

  • We have a collection of users
  • Each item in the collection is a user object with details data (id, name, email etc)
  • Each user record has a collection called notes
  • Each record in the note collection has a note object with  details data (id, title, text etc)

I am sure there’s a better way to understand this, maybe you can leave a comment below and share how you understand it.

Ohh and how do we add a notes record to it? That’s pretty simple too, all we do is add a note object to the notes collection.

addNote(note) {
   return this.notesCollection.add(note);
}

That’s all it is really, instead of thinking rows and columns think of it as collections, objects and nested collections. The image below of the Firestore DB in the Firebase console should give you an idea of how to data is structured,

I am sure you can see nested collections above, we have a users collection which has user details within which we have our notes collection data. 

Summary

I think that covers everything that I wanted to say in this post. Like I said before, the problem that I was solving here was quite simple, it just needed a slightly different mindset to solve it. All the code I shared above were just brief code samples to get my point across. If you want to see the full code sample, you can look at it here on Github. Remember, if you want that Github project to work, you will need to create environments/environment.ts  file in the app/src  to store your Firebase project configuration. If you don’t know how to do that, maybe this tutorial can help you.

Leave us a comment below and tell us how you do things with Ionic and Firebase?

As usual, if you find any of my posts useful support us by  buying or even trying one of our products and leave us a review on the app store.

‎Snap! I was there
‎Snap! I was there
Developer: Bhuman Soni
Price: $3.99
‎Captain's Personal Log
‎Captain's Personal Log
My Simple Notes
My Simple Notes
Developer: Bhuman Soni
Price: Free

Leave a Reply

Your email address will not be published. Required fields are marked *