Syncing Data With Firebase Using Ionic Framework

Lately there has been a lot of buzz about Firebase and now that it has been bought by Google, it is probably only going to get bigger.   Firebase has a very thorough datastore API making it very useful for applications that can leverage JavaScript.

Now you might be asking yourself, well can’t I use the Dropbox datastore API that you mentioned in one of your previous articles?  You absolutely can, however, Firebase is a far better solution when creating a service because the data isn’t sandboxed to a specific user like Dropbox.

In this example, we’re going to create a simple Apache Cordova Android and iOS application using Ionic Framework.

There are a few things we’ll need in order to make this application successful:

With this in mind, let’s start by creating security rules for our Firebase application.  In your Firebase dashboard add the following:

The above basically says, allow all users to write to the users node, but only allow a matching authenticated user to read from the matching node.  We do this so anyone can create a user account in our application, but users can only read from their own account.

Now it is time to create a fresh Ionic project for Android and iOS:

Note that if you’re not on a Mac, you cannot add and build for the iOS platform.

This project doesn’t require any Apache Cordova plugins, so we can go straight into adding the required Firebase libraries into our project.  Download the Firebase JavaScript library and the AngularFire library and import them into your js directory.  Open your index.html file and include the following lines:

Open your www/js/app.js file and include the Firebase directive in your angular.module method.  It will look something like this:

We are going to follow the AngularFire documentation pretty closely at this point.  It can get a little confusing, but I’m going to try to ease you into it.

If you aren’t already familiar with the AngularJS UI-Router, I suggest you read my previous post because it will be used going forward.

To keep things simple, we are going to have only two screens / states:

  • Sign in / register
    • Allow for password based use.  If the username does not exist, create an account and sign in.  Otherwise just sign in.
  • Todo list
    • Add items to the todo list and view them

For efficiency we are going to make one object instance for Firebase.  Outside the AngularJS code declare a variable we’ll use for Firebase.  In the end, you should have something that looks like this:

Notice the highlighted lines.  The fb variable will be used throughout our application.  As I mentioned earlier, we are going to be using the AngularJS UI-Router, so make sure you’ve reviewed it.

The above code will set up the states that we plan to use.

Remember that at this point your index.html file should look something like this:

We’re now going to jump straight into the design of our UI states.  Let’s start with our login screen, so open templates/login.html and make it look like the following:

Notice the highlighted lines in the above code.  For simplicity purposes we are going to be using Firebase username and password authentication which is why there is a username and password field rather than a Facebook or Twitter authentication button.  Based on the state configuration and the login(email, password) and register(email, password) methods found in the login.html file, we will end up with the following in our app.js file:

The register(username, password) method follows the official AngularFire documentation pretty much exactly.  The login(username, password) method is just a stripped version of the register method that we used.  It just doesn’t contain the $createUser code.

Essentially what the register method does is create a user to the application and then sign that user in.  The login method just signs the user in.

When the application has redirected from the login state to the todo state, the user will see a list of items defined with the following UI code in the templates/todo.html file.

Upon first launch, the user won’t have any items in there TODO list.  This is why we have the create() method one of our navigation buttons.  We’ll get into this more, soon.  In the mean time, add the following controller to your app.js file.

Both these methods are used in the templates/todo.html file where list() initializes the Firebase data and create() adds to the list.  Let’s start by looking at the list() method since it is the first thing fired when the screen displays.

Before trying to get any data, we need to validate that we are signed into an existing Firebase account.  This was done using the getAuth() method, however, notice that I didn’t use the AngularFire version of this method.  It is up to you, but there does exist a $firebaseAuth.$getAuth() version of this method.  Either will work fine.

If the user is signed in, we need to get the unique id found in the fbAuth.uid property.  As per the official AngularFire documentation, we are going to create an object out of the users/auth.uid that will be synchronized consistently in two directions.  The auto-synchronizing object we create will be found as $scope.data and can be used like any AngularJS object.

Now let’s take a look at the create() method for adding new items to the list:

For simplicity we are only going to use an $ionicPopup rather than creating a new screen for adding list items.  By default, when you create a new user, no data will exist in the database until you have something to save.  The goal is to have our database structure look like the following:

Per the auto-synchronizing object that we created, $scope.data represents example/users/auth.uid, but like I said, first time users don’t even have anything in the database yet beyond this.  This is why we check to see if the todos property exists and if it doesn’t, make a blank array out of it.  Then we can proceed in pushing new array elements to it.

Just like that you have data that can be synchronized across devices and platforms.  Everything is handled for you with the Firebase library.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • chandramuralis

    Thanks for the detailed article. Would be great if you could share the source code via GitHub or plunker.

    • Hi,

      I try to avoid posting code demos of my articles, because I’d like to think the written and video combination I do is good enough to reproduce. I’d rather have everyone go through the steps, and ask questions as necessary. It helps to build a stronger understanding of the subject.

      If you’ve gone through the video and written portion and have questions, don’t hesitate to ask.

      Regards,

      • chandramuralis

        I agree with you…. It is good to redo the same as you explained in your article.

  • Juukie14

    Thanks for sharing, was fun to read.

  • Amy

    Hi

    I have followed both your video and tutorial but the code is just not working for me can you help?

    • Are you getting errors? What exactly isn’t working? Device or simulator? Android or iOS?

      I’m happy to help.

      Regards,

      • Amy

        No errors. It doesn’t go to the states for some reason it just stays on index.html and I have added the

        I just ran it like how you did in your video. I used firefox.

        • Even with states, you will still be on index.html. The routing system is just templating.

          Would you mind putting your project on GitHub? You can falsify the Firebase URL if it makes you feel any better.

          Regards,

          • Anthony-H

            hey Nic, thanks for all the great guidance so far! — I’m running into the same difficulty.. any idea what was the fix for Amy above?

          • Without seeing your code on GitHub, it does make things tough.

            When you load the page, is it blank? You say there are no errors, but can you explain in detail what is happening to give me a better idea?

            Regards,

          • Anthony-H

            Sorry, there are 3 errors, – failed to load resource (cordova.js) -syntax error in app.js -Module ‘starter’ is not available — is this a naming issue? i left it the same as your example

          • The cordova.js error is probably fine because I assume you’re testing in your web browser. The other two could be the reasons for your problems. Can you please try to put your code on GitHub or Pastebin? This is like trying to find a needle in a haystack while having no sight. Not very efficient.

            Regards,

          • Anthony-H
          • In your config method can you put a / in your otherwise method?

            otherwise(“/login”)

            That might be the issue.

          • Anthony-H

            line 44? this wasn’t the fix…

            Is there anywhere else I should be calling ‘starter’ or anything….

            My address in the navigation bar ends with ……index.html
            No #login..

          • I ran your code through a linter and found a few issues that could be causing the problem:

            Line 26 is missing a semi-colon
            Line 45 has a colon instead of a semi-colon

            Let me know if either of those fixes your problem.

          • Anthony-H

            Hey, thanks Nic but still no joy…

            Here’s a link to the same errors I’m getting http://pastebin.com/pY8Lbr0T

          • What does your index.html look like?

          • Anthony-H
          • I further looked at your logs and saw this:

            Then according to your Pastebin, it relates to this line:

            Why are you wrapping your function parameters in quotation marks? That is why you are getting a syntax error. The same problem exists on line 64.

            That could be preventing your application from loading completely. Fix that and let me know.

            Regards,

          • Amy

            Hi sorry got caught up with other things here is my link https://gitlab.com/aimiforgan/firebaseExample.git

          • You had two errors in your code. Why you didn’t see them in your logs is beyond me because my logs showed them immediately.

            Line 29:

            You’re missing a comma. The same problem exists on line 34:

            Both these errors could have been identified before testing if you ran your code through a linter first. You can see an example here:

            http://ionicframework.com/blog/minifying-your-source-code/

            Regards,

  • Barry Mc Gettigan

    Hi, thanks for the tutorials. I`m getting this error in my console:
    Error: [$injector:unpr] Unknown provider: $firebaseAuthProvider <- $firebaseAuth <- LoginController. Can you advise how to fix this? Thanks

    • Did you forget to include $firebaseAuth in your LoginController directive list? Or misspell it by chance?

      Without seeing your code or full error logs, I cannot advise further.

      Regards,

      • Barry Mc Gettigan

        Thanks for replying. Everything appears to be correct in my code but still no joy. Its more the posting the todos to Firebase that Im interested in, rather than the login and register functions, because I`m having awful trouble figuring out how to submit forms to a database. Cheers anyway.

        • Without seeing your code or logs, I cannot help you further.

          Sorry,

        • Matt Heering

          I think you need to “Enable Email & Password Authentication” from your firebase control panel.

  • confused

    Hi

    I am getting the following error on the ToDo page could you please help?
    Error: [$compile:ctreq] Controller ‘ionNavBar’, required by directive ‘ionNavButtons’, can’t be found!

    • It helps when you stop changing your display name in the comment ts section. Previously you were calling yourself Amy. You had asked previous Firebase questions, but never responded back. Do those work now?

      This sounds like a general Ionic Framework question rather than an issue with Firebase. I’m happy to help, but for these it is best to post in the forums. What are the full error logs? Also please put your code on GitHub.

      Regards,

      • confused

        yes it worked thanks for getting back

  • Damian Batson

    hey Nic. thanks for the intro! having an issue saving todos, when i add a new todo it overwrites the existing one in the JSON as opposed to making a list. any suggestions?

    • Are you pushing todo elements to the array?

      Put your code on GitHub please.

      Regards,

      • Damian Batson
        • You’re doing a lot of manipulations beyond what I do in my tutorial. Can you please follow it exactly and tell me your results.

          Regards,

          • Damian Batson

            thanks for having a look at my repo. i’ve swapped out the $asObject for a $asArray instead. makes it easier to persist the data to an array. thanks again and keep up the good work!

  • Guest

    Hi,

    I’ve been watching a lot of your Ionic videos – very nice work!

    But in this exampel, I keep getting this error: TypeError: Cannot read property ‘hasOwnProperty’ of undefined

    It happens when I click OK in the popup window.

    Can you, or any one else, see what Im doing wrong?

    Thanks!

    Here is my code:

    // Ionic Starter App

    // angular.module is a global place for creating, registering and retrieving Angular modules

    // ‘starter’ is the name of this angular module example (also set in a attribute in index.html)

    // the 2nd parameter is an array of ‘requires’

    var example = angular.module(‘starter’, [‘ionic’, ‘firebase’])

    var fb = null;

    example.run(function ($ionicPlatform) {

    });

    example.config(function ($stateProvider, $urlRouterProvider) {

    });

    example.controller(“LoginController”, function ($scope, $firebaseAuth, $location) {

    });

    example.controller(“TodoController”, function($scope, $firebase, $ionicPopup){

    $scope.list = function(){

    }

    $scope.create = function() {

    }

    });

    • Peter Lauge

      Hmm – I can not delete this.
      If you can, please do that.

  • Peter Lauge

    Hi,

    I’ve been watching a lot of your Ionic videos – very nice work!

    But in this exampel, I keep getting this error: TypeError: Cannot read property ‘hasOwnProperty’ of undefined

    It happens when I click OK in the popup window.

    Can you, or any one else, see what Im doing wrong?

    Thanks!

    Here is my code:

    // Ionic Starter App

    // angular.module is a global place for creating, registering and retrieving Angular modules

    // ‘starter’ is the name of this angular module example (also set in a attribute in index.html)

    // the 2nd parameter is an array of ‘requires’

    var example = angular.module(‘starter’, [‘ionic’, ‘firebase’])

    var fb = null;

    example.run(function ($ionicPlatform) {

    $ionicPlatform.ready(function () {

    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard

    // for form inputs)

    if (window.cordova && window.cordova.plugins.Keyboard) {

    cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);

    }

    if (window.StatusBar) {

    StatusBar.styleDefault();

    }

    fb = new Firebase(“https://xxxxxx.firebaseio.com/”);

    });

    });

    example.config(function ($stateProvider, $urlRouterProvider) {

    $stateProvider

    .state(“login”, {

    url: “/login”,

    templateUrl: “templates/login.html”,

    controller: “LoginController”

    })

    .state(“todo”, {

    url: “/todo”,

    templateUrl: “templates/todo.html”,

    controller: “TodoController”

    })

    $urlRouterProvider.otherwise(“/login”);

    });

    example.controller(“LoginController”, function ($scope, $firebaseAuth, $location) {

    $scope.login = function (username, password) {

    var fbAuth = $firebaseAuth(fb);

    fbAuth.$authWithPassword({

    email: username,

    password: password

    }).then(function (authDate) {

    $location.path(“/todo”);

    }).catch(function (error) {

    alert(“Error: ” + error);

    });

    };

    $scope.register = function (username, password) {

    var fbAuth = $firebaseAuth(fb);

    fbAuth.$createUser(username, password).then(function () {

    return fbAuth.$authWithPassword({

    email: username,

    password: password

    })

    }).then(function (authDate) {

    $location.path(“/todo”);

    }).catch(function (error) {

    alert(“Error: ” + error);

    });

    }

    });

    example.controller(“TodoController”, function($scope, $firebase, $ionicPopup){

    $scope.list = function(){

    var fbAuth = fb.getAuth();

    if(fbAuth){

    var sync = $firebase(fb.child(“users/”+fbAuth.uid));

    var syncObject = sync.$asObject();

    syncObject.$bindTo($scope, “data”);

    }

    }

    $scope.create = function() {

    $ionicPopup.prompt({

    title: ‘Enter a new TODO item’,

    inputType: ‘text’

    })

    .then(function(result) {

    if(result !== “”) {

    if($scope.data.hasOwnProperty(“todos”) !== true) {

    $scope.data.todos = [];

    }

    $scope.data.todos.push({title: result});

    } else {

    console.log(“Action not completed”);

    }

    });

    }

    });

    • Peter Lauge

      I created a new database and now it’s working 🙂

      • Glad to see you were able to get it working 🙂

  • Husam

    Thanks Nic for sharing this!

    In case someone using the latest version of angularfire 1.0 here is an update:

    // In LoginController
    fbAuth.$createUser({
    email: username,
    password: password
    }).then(function() { … —> the reset same

    // In TodoController
    app.controller(“TodoController”, function($scope, $firebaseObject, $ionicPopup) { —> replace $firebase with $firebaseObject.

    if(fbAuth) {

    I hope this helpful

    • Hey, thanks for reminding me of this! I updated my other Firebase tutorials to reflect AngularFire 1.0, but forgot about this one.

      I’ll update the post hopefully real soon!

      Regards,

  • Jan Ika

    hey please help.. I followed this tutorial exactly,, and when i compile and load the app to my phone *creating .apk via phone gap) all i get is a blank screen upon load.

    • Before I look at your code, what do your logs say? Blank screen means you’re going to get an error message in your logs.

      Regards,

  • hey nice tutorial..but i want to do something even stricter with the firebase auth rule..
    In my app i am not registering or logging in a user what i want is to authenticate the “app” itself and not the user, what i mean is that i want everyone to read my data(without login) off my firebase but ONLY IF they are using my app..possible??

    currently the rule is like so:

    {
    “rules”: {
    “.read”: true,
    “$masterNode”:{
    “.write”:”auth !==null && auth.uid===’simplelogin:99′”
    },
    “users”:{
    “.write”:false
    }
    }
    }

    • To my knowledge blocking the data store to work with only your application is not possible because there is no way to truly determine that the user is using your application.

      If you really wanted to pursue this, you might be able to hack something together using ciphers, but it still wouldn’t truly be protected. By ciphers I mean encrypt all data in your app using a hard coded key. This way without the key the data in Firebase is useless. I did something like this here:

      https://www.airpair.com/ionic-framework/posts/ionic-firebase-password-manager

      However, like I said it is not fool proof. If someone finds your cipher key, they can just add it to their application.

      My advice would be to not pursue the idea of blocking the database on an app level.

      Regards,

  • Yanupla

    Great Nic, this is awesome!

    • No problem! I’m glad you enjoyed it 🙂

  • Mohamed Mehrez

    Hi Nic,this is Awesome ! you led me here and i keep learning from you.
    Any ideas on how to trigger the logout ? and how to redirect to login page if the session is over ?
    That would be very helpful. Thanks!

  • eshinkawa

    Nic, congrats for this tutorial. Would you consider making a new one explaining how to make a facebook login and storing data in Firebase? Thanks a lot.

  • Nic, I just found your article and it’s awesome. Thank you for sharing.
    How can I display the records in reverse order? In other words, the most recent entry to show at the top of the list

    • Abu

      I know each item has a unique ID but it might be worth writing a unique incremental ID to the DB along with your entry. With that, you can always use angulars orderBy and then something like

      I’m a novice myself so i might be wrong 🙂

  • Earl

    congrats as always!
    I am syncing data with Firebase in this way but i have noticed that it has a lot use of CPU, i think its because of the web sockets and the app even in background uses the web socket to synch. What do you think i can improve the performance of the app?
    Thanks!

    • Well, maybe use the realtime sync capabilities only when you really need them. For data which you want to read or write only occasionally you can use “ref.once(…)” to access it on a one-off basis. If you call “ref.once(…)” you don’t keep sockets open.

      • Earl

        Yes, I ended up doing like that 🙂

        thanks for the answer!

  • Amir Yacaman

    Did anyone come across this error yet? — Error: undefined is not a function (evaluating ‘syncObject.$bindTo($scope, “data”)’)

  • Rahul Matta

    Thanks for this article! I’ve followed it exactly, but I’m still getting this error.

    Error: permission_denied: Client doesn’t have permission to access the desired data.

    Any ideas?

    • The user needs to be logged in (using auth.$authWithPassword) and you need to have your Firebase security rules correct, for instance:

      {
      “rules”: {
      “.read”: “auth != null”,
      “.write”: “auth != null”,
      “messages”: {
      “$uid”: {
      “.write”: “auth != null && auth.uid == $uid”
      }
      }
      }

      etcetera.

  • Isaac Sanchez

    Hey Nic

    is it possible to use firebase and s3 together. I need to store images and firebase can get pricy. Could I use s3 to store the images and save the url (from s3) to firebase as a string. And then call the url as needed from firebase?

    Thanks

    • Yes this is perfectly possible, it’s is exactly what I’ve done in my app. I store the image in AWS S3 and I store only the AWS S3 URL in Firebase. This way I consume much less Firebase database space and transfer bandwidth. Oh and it’s not only cheaper but probably also faster and more efficient (using less memory) than using a Firebase “blob” and a data URL.

  • Shane Lester

    Nic, this is great. I had to remove the tags in index.html to make the views load for some reason.
    I can get this to run via ionic serve and in the Ionic View app but the Ionic View won’t update the database- is this related to the View App? If so- is there any other way to test this on iOS without a Mac?

  • Wells Luke

    Awesome tutorial, Nic.
    I was wondering if there’s a way to have multiple inputs in the prompt box as I’m trying to get it to save a few different bits of information to the user’s account, such as their name, phone number and address.
    Cheers

  • shanthi

    “ERROR: Error: The specified authentication provider is not enabled for this Firebase.” on fbAuth.$createUser and also on fbAuth.$authWithPassword. Can you please tell me why this error comes??

    • Felipe de Araujo

      I am having this same issue and I already enabled the right providers on the dashboard.

  • Roopa N

    Hi nic,,
    Thanks for this wonderful article…But i have a issue with popup during signin or registration.Am not getting any sort of popups

  • sanborN

    I always get the: Cannot read property ‘hasOwnProperty’ of undefined Error. I dont know why this happens!! 🙁

    • Guille Acosta

      I’m getting same error.. :/

      • Guille Acosta

        I was reloading my page instead to came back to initial url where fb connection is loaded.

  • gugasevero

    Hi Nic!
    I’m almost there kkkk
    When I try to register a user a popup the following message:
    “ERROR: error: the especified authentication provider is not enabled for this Firebase”.
    What’s wrong? I have to do anything else in Firebase?
    Thank you for your attention.

    • gugasevero

      Nic

  • saykopat 1001

    Hi Nic , your code one line not work var syncObject = $firebaseObject(fb.child(“users/” + fbAuth.uid));

    you help me ?

  • Suresh

    Hi Nic,
    I have some issues in registering / logging in..Even though i created a Firebase account, whenever i click login / Register, i get a error popup saying INVALID FIREBASE SPECIFIED.
    Please find the screenshot.
    Does this mean that the firebase account is not activated…?
    My source code is attached in google drive:
    https://drive.google.com/file/d/0B5v6NTVDLpYqUHFVWkRDb3ROSkE/view?usp=sharing

    Let me know your comments..

    Regards
    Suresh

  • Gajendrasinh Zala

    Hi,

    i’m use same code as par above but i got “ERROR: Error: Projects created at console.firebase.google.com must use the new Firebase Authentication SDKs available from firebase.google.com/docs/auth”

    how can i solve this

  • Guille Acosta

    Hi Nic, this tutorial worked great! Thank you.
    I used it for a bigger project where I need to compare data from users, do you know how could I query among, for example, ‘titles’ from ALL users’ todos? As you know all users have a distinct auth.uid and because of secury rules I need be logged to access data, so I have not idea how to query it.
    If you can link me a doc to start learning, would be fantastic.

  • Chael Gutierrez

    hi Nic…can I ask a question? what backend should I use in IOnic framework? and database…Best answer please Im new to IONIC Framework

  • Bilal Yaqoob

    This is the old article, Can you please update it