Creating a basic Contacts app with Firebase and AngularJS

In this tutorial, we will create a basic contacts app using AngularJS and Firebase. We are going to assume that you have basic understanding about using AngularJS.

Introduction to Firebase

It is a mobile development platform by Google. It provides products such as database, storage, authentication, messaging, analytics and more. Developers can start working on their apps without writing server-side code. It provides APIs to handle things like database, authentication, etc. on front-end. It can easily scale from small to large apps as it is based on Google Cloud infrastructure. Firebase Realtime database stores data in a JSON tree structure. You can store key-value pairs and create nested levels of data, like how JSON data is structured. But it can’t store real arrays.

What is AngularFire?

Firebase provides a Javascript SDK which provides various APIs to work with. AngularFire is a helper library. It aims to remove boilerplate involved in creating AngularJS bindings for Firebase APIs. It provides extra features like 3-way data-binding and array handling which makes integration between AngularJS and Firebase easier. AngularFire does not replace the SDK, rather it supplements it. You can use AngularFire APIs or native APIs depending upon what makes your work easier.

Setting Up Realtime Database:

Go to firebase.com to create a free account. Then go to Firebase Console and create new project.

Creating Project

Now, go to Database under Develop section on the left-side. Click Get Started under Realtime Database.

Selecting Database

Enable Start in test mode. To keep things simple for this tutorial, we are going to use test mode. It makes the database open to read and write publicly. Don’t worry, you can change these settings later on.

Test Mode

Setting up project files:

Step 1: Create index.html as following:

<!DOCTYPE html>
<html ng-app="app">

 <head>

 <meta charset="utf-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">

 <title page-title></title>

 <link href='http://fonts.googleapis.com/css?family=Open+Sans:400,300,600,700' rel='stylesheet' type='text/css'>
 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" />
 <link rel="stylesheet" href="https://cdn.datatables.net/1.10.16/css/dataTables.bootstrap.min.css" />

 <style>
 body{
     font-family:”Open Sans” , sans-serif
 }
 </style>
 </head>
 <body>
 <nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <div class="navbar-header">
            <a class="navbar-brand" href="#">Address Book</a>
        </div>
       <ul class="nav navbar-nav">
          <li><a ui-sref="home">Home</a></li>
          <li><a ui-sref="add">Add</a></li>
       </ul>
    </div>
 </nav>
 <div ui-view></div>

 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
 <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>
 <script src="//unpkg.com/@uirouter/angularjs/release/angular-ui-router.min.js"></script>
 <script src="https://www.gstatic.com/firebasejs/3.6.6/firebase.js"></script>
 <script src="https://cdn.firebase.com/libs/angularfire/2.3.0/angularfire.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.16/js/jquery.dataTables.min.js"></script>
 <script src="https://cdn.datatables.net/1.10.16/js/dataTables.bootstrap.min.js"></script>
 <script src="https://cdnjs.cloudflare.com/ajax/libs/angular-datatables/0.6.2/angular-datatables.min.js"></script>

 <script>
 // Initialize Firebase
 var config = {
    apiKey: ********************,
    authDomain: ********************,
    databaseURL:********************,
    projectId: **********************,
    storageBucket: **********************,
    messagingSenderId: **********************,
 };
 firebase.initializeApp(config);
 </script>
 <script src="scripts/app.js"></script>
 <script src="scripts/config.js"></script>
 <script src="scripts/controllers.js"></script>
 </body>
 </html>

Now, open your newly created project on Firebase console. Click “Add Firebase to your web app” and copy the initialization code. Don’t copy the first script tag as we have already added it earlier in the index. Replace the initialization code in index.html with it.

Initializing Firebase

 

Step 2: Create a scripts folder and create following files:
app.js

angular.module('app', [
        'ui.router',
        'firebase',
        'datatables'
    ])

Here we need to import modules of Angular UI Router, AngularFire and datatables (to be explained later).

config.js

function config($stateProvider, $urlRouterProvider) {
    $urlRouterProvider.otherwise('/home');
    $stateProvider
       .state('home', {
            url: "/home",
            templateUrl: "views/home.html"
        })
        .state('add', {
            url: "/add",
            templateUrl: "views/add.html"
        })
}

angular
    .module('app')
    .config(config)

Then we setup the URL and pages for the Home and Add pages using Angular UI Router. /home is set to be the default page using $urlRouterProvider.

 

Step 3: Create a views folder and create home.html file with just “Hello World!” text.
Create add.html page as:

<div class="container" ng-controller="addContactCtrl">
<form ng-submit="add()">
    <div class="form-group">
        <label>Name</label>
        <input type="text" class="form-control" ng-model="formData.name">
    </div>
    <div class="form-group">
        <label>Address</label>
        <input type="text" class="form-control" ng-model="formData.address">
    </div>
    <div class="form-group">
        <label>Phone No.</label>
        <input type="text" class="form-control" ng-model="formData.phone">
    </div>
    <button class='btn btn-default' type="submit">Save</button>
</form>
</div>

Here the input text is stored in the formData object using ng-model. When the user submits the form, add function is executed.
Add function will store the new person’s details in Firebase.

 

Step 4: Create controllers.js and add the following code:

function addContactCtrl($scope, $state, $firebaseObject) {

    let ref = firebase.database().ref('Contacts');
    let pushKey = ref.push().key;
    $scope.formData = $firebaseObject(ref.child(pushKey));

    $scope.add = function(){
        $scope.formData.$save().then(() => {
            $state.go('home');
        });
    }
};
angular
    .module('app')
    .controller('addContactCtrl', addContactCtrl)

Add page now looks like this:

Add Contact Page

Let’s explain it step by step:

  1. Here we have used AngularJS Dependency Injection to use $scope, $state and $firebaseObject services. $scope is used to connect the views with the controller and access data on both sides. $state is used to redirect the user to different ‘states’ or links declared earlier in config.js. Finally $firebaseObject is an AngularFire service to get and save data in Firebase.
    function addContactCtrl($scope, $state, $firebaseObject) {
  2. To add, change or remove data in Firebase, we need to get a reference to a specific location in the database. For this tutorial, the contact details are stored in ‘Contacts’ key. So, the reference points to /Contacts.
    wlet ref = firebase.database().ref('Contacts');
  3. Firebase SDK provides a feature called push keys. These are randomly generated keys which can be used as unique keys to store data, without worrying about data getting overwritten by someone else.
    AngularFire does not directly generate these keys. So we have to use a native Firebase method for this purpose. To generate a push key, add .push() to a reference. It returns an object containing the push key. This key is stored into the pushKey variable.

    let pushKey = ref.push().key;
  4. Here, we have added a child reference to the reference we already created. So if the push key generated was ‘abcd’, then the the new reference now points to /Contacts/abcd. $firebaseObject is an AngularFire function. It takes in a Firebase reference and returns a customized object which contains the data at the reference location and some helper methods.
    If some data is already stored at /Contacts/abcd, it is automatically downloaded in the returned object. $scope.formData is the variable used earlier in add.html to store the contact details of a new user. This data is now stored in the object returned by $firebaseObject.

    $scope.formData = $firebaseObject(ref.child(pushKey));
  5. This function runs on form submit. To save contact details in Firebase, $save method is called on a $firebaseObject. $save is an AngularFire method. Any data added to $scope.formData through ng-model will get saved directly in Firebase.
    $save returns a promise. In its .then function, we use $state.go to redirect the user to the home page after a contact gets saved in firebase.

    $scope.add = function(){
        $scope.formData.$save().then(() => {
            $state.go('home');
        });
    }

What is Datatables?

It is a jQuery plugin which is used to create tables which can be easily sorted, filtered and edited. It’s packed with features but we going to setup a very basic table using it’s Angular JS plugin ie, Angular-DataTables.

Setting up DataTables:

Step 1: Create home controller to get contacts from Firebase

function homeCtrl($scope, $firebaseObject){
    const ref = firebase.database().ref('Contacts');
    $scope.contacts = $firebaseObject(ref);
}
angular
    .module('app')
    .controller('homeCtrl', homeCtrl)
    .controller('addContactCtrl', addContactCtrl)

Here we created a reference to the Contacts key in Firebase and downloaded its data in $scope.contacts using $firebaseObject.

Step 2: Create home.html in views folder

<div class='container' ng-controller="homeCtrl">
<table datatable="ng" class="table row-border table-striped table-hover compact display">
    <thead>
    <tr>
        <th>Name</th>
        <th>Address</th>
        <th>Phone No.</th>
    </tr>
    </thead>
    <tbody>
      <tr ng-repeat="contact in contacts">
        <td>{{contact.name}}</td>
        <td>{{contact.address}}</td>
        <td>{{contact.phone}}</td>
      </tr>
    </tbody>
</table>
</div>

Here we have initialised datatables using the datatables=”ng” directive. It specifies that the data in the table is rendered using AngularJS.
In tbody, ng-repeat directive creates rows for every contact in $scope.contacts object.

Home Page
And thus, the basic contacts app is now complete. You are free to improve it by adding more features like editing or deletion of contacts.

References

Further reading

Creating a basic Contacts app with Firebase and AngularJS was last modified: August 6th, 2018 by Harshit Jain