Build a Real-Time Scheduling App using AngularJS and Firebase

Free Course

Getting Started with Angular 2

Angular 2 is the shiny new framework that comes with a lot of new concepts. Learn all the great new features.

Real-time applications provide so much functionality across so many different types of applications. There’s Google Drive real-time editing, Twitter showing new tweets, any new chat system built recently, and so many more.

It’s always good to learn how to make these sorts of techniques by learning things like socket.io and using that with Node.js.

An alternative to building the entire backend yourself is to use a cool service called Firebase.

What is Firebase

Firebase is an API service to store and sync data in real-time. What this means is that you don’t have to worry about the backend server, database, or real-time component (socket.io). All of that is handled for you by Firebase.

Just grab data from Firebase, save data to Firebase, and Firebase will worry about saving, and also syncing across all connected devices/sites. Piece of cake!

You just have to worry about the frontend part of your application.

firebase

Firebase just recently joined Google, so the platform has great support and is planning to stick around and continue to grow.

Here are some quick demos. You can press the Play button to see the real-time sample chat application. Also, click on the provided link https://xxxxxxxx.firebaseio-demo.com to see the updates happen in real-time on the Firebase dashboard. The dashboard allows us to see our data and see its changes.

Let’s build a sample application with Firebase so we get a stronger understanding of what it does.

Our Sample Application

We’re going to build a scheduling application where people can book times to meet with you. This will be a simple concept similar to something like youcanbook.me. We also want our version to be real-time.

Requirements:

  • Show available dates and availability
  • If somebody books a slot, make it unavailable for everyone
  • Use AngularJS/HTML/CSS as the frontend
  • Use Firebase as the backend

Here’s a quick demo. You can see the left side is the actual application where we can book times. The right side is the Firebase dashboard where we can see changes happen in real time.

This demo provides a good amount of functionality, and a lot of it will thankfully be handled by Firebase. Let’s get to the code.

Setting Up

The following files are needed for this demo:

- index.html
- style.css
- app.js

index.html will hold all of our HTML markup

style.css is the basic stylings. We will also be pulling in Bootstrap to handle some styling duties.

app.js will hold our Angular module code. This is where we will connect to Firebase and sync our data to and from the Firebase service.

Let’s set up the foundation needed for our files.

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Angular Scheduling</title>

    <!-- CSS -->
    <!-- load Bootstrap and custom style.css -->
    <link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootswatch/3.3.0/journal/bootstrap.min.css">
    <link rel="stylesheet" href="style.css">

    <!-- JS -->
    <!-- load Angular, Firebase, Firebase Angular Library, and custom app.js -->
    <script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.0/angular.min.js"></script>
    <script src="https://cdn.firebase.com/js/client/1.1.1/firebase.js"></script>
    <script src="https://cdn.firebase.com/libs/angularfire/0.8.0/angularfire.min.js"></script>
    <script src="app.js"></script>
</head>
<body>
<div class="container" ng-app="scheduleApp" ng-controller="mainController">
  
  <div class="page-header text-center">       
    <h1>Schedule City</h1>        
  </div>

  <!-- were doing one day with 1 time slot for simplicity -->
  <!-- we'll use angular's ng-repeat in a bit to get the other days and times -->
  <div class="row times">

    <div class="col-xs-4 text-center">
              
      <h2>Monday</h2>
      
      <div class="time-slot">       
        <input type="checkbox" id="monday-time">
        <label for="monday-time">9:00am</label>
      </div>
    </div>    

  </div>

  <p class="text-center">    
    <a href="#" class="btn btn-primary">Reset</a>
  </p>

</div>  
</body>
</html>

We are hiding the input box and using the label as the clickable item. In order for this to work, we will need to make sure the label has a for attribute that points to the id of the input.

This technique has been used on our previous tutorials like: Lightsaber Checkboxes and Google Polymer Checkboxes.

CSS

Let’s go into our style.css file and get our styling out of the way.

/* checkbox - each time slot */
.time-slot               {  }

/* hide the checkbox itself - the label will be styled */
.time-slot input     { 
  display:none; 
}

/* default styling for our labels */
.time-slot label     { 
  padding:10px 20px; 
  color:#FFF; 
  cursor:pointer; 
  background:#EEE; 
  border-radius:5px; 
  transition:0.3s ease all;
}

/* if the label is checked */
.time-slot input:checked ~ label { 
  background:#f2dede; 
  cursor:not-allowed;
  animation:flashBooked 0.5s ease; 
}

/* if the label is not checked */
.time-slot input:not(:checked) ~ label { 
  background:#6AB074; 
  animation:flashAvailable 0.5s ease; 
}

/* animation for the time slot to flash red */
@keyframes flashBooked {
  0%, 100%  { background:#f2dede; transform:scale(1); }
  50%       { background:#F99090; transform:scale(1.5); }
}

/* animation for the time slot to flash green */
@keyframes flashAvailable {
  0%, 100%  { background:#6AB074; transform:scale(1); }
  50%       { background:rgb(119, 218, 78); transform:scale(1.5); }
}

Vendor Prefixes: For simplicity, we aren’t adding the vendor prefixes like -moz- or -webkit- so be sure to add that in your final projects.

firebase-first-css

Now we have the foundation for our application. Right now, it’s not very dynamic though since it doesn’t pull in any real data. Let’s plug in Angular and Firebase so we have real data now.

JS (AngularJS)

We’re going to lay out the foundation of our Angular application right now. We’ll walk step by step after this to integrate with Firebase.

// create our angular module and inject firebase
angular.module('scheduleApp', ['firebase'])

// create our main controller and get access to firebase
.controller('mainController', function($scope, $firebase) {
  
  // our application code will go here
  
});

With our foundation ready to go, let’s start working with Firebase.

Connecting to and Using Firebase

We will first need to create a Firebase account. After creating an account, Firebase will set us up with a sample application on their Hacker Plan.

firebase-first-app

The URL here (burning-torch-4263.firebaseIO.com) will be your own personal application address. You can click on this to get to the backend dashboard for your application.

Now that we have that application URL, we can connect to our application from within our Angular code.

Creating the Connection

To create the Firebase to Angular connection is very easy. Firebase provides a library specific to Angular called AngularFire. We already added it to our project by linking to the script in our HTML and injecting firebase into our Angular application.

// create our angular module and inject firebase
angular.module('scheduleApp', ['firebase'])

// create our main controller and get access to firebase
.controller('mainController', function($scope, $firebase) {
  
  // connect to firebase 
  var ref = new Firebase("https://burning-torch-4263.firebaseio.com/days");  
  var fb = $firebase(ref);
  
});

That’s all we need to connect! It’s interesting to note that we have added days to the end of our URL. You are able to use the URL as a sort of way to map to your data. Everything that we do now will be saved in the days object in our database.

Let’s create the sample data and wire it up to our Reset button now. This way, we can have data to actually look at.

Setting Data

The fb object we created gives us some functions to grab and set data. The Firebas guide does a good job of showing how you can set and get data so be sure to take a look at that. Let’s create data for 2 days (Monday and Tuesday) and for 2 times each.

We will create an Angular function to create the data and then point our Reset button to that function.

// create our angular module and inject firebase
angular.module('scheduleApp', ['firebase'])

// create our main controller and get access to firebase
.controller('mainController', function($scope, $firebase) {
  
  // connect to firebase 
  var ref = new Firebase("https://burning-torch-4263.firebaseio.com/days");  
  var fb = $firebase(ref);

  // function to set the default data
  $scope.reset = function() {    

    fb.$set({
      monday: {
        name: 'Monday',
        slots: {
          0900: {
            time: '9:00am',
            booked: false
          },
          0110: {
            time: '11:00am',
            booked: false
          }
        }
      },
      tuesday: {
        name: 'Tuesday',
        slots: {
          0900: {
            time: '9:00am',
            booked: false
          },
          0110: {
            time: '11:00am',
            booked: false
          }
        }
      }
    });    

  };
  
});

We will be setting this object of monday and tuesday to our days section of our database.

Now, we just have to wire up our reset button.

<p class="text-center">    
    <a href="#" class="btn btn-primary" ng-click="reset()">Reset</a>
  </p>

Just like that, we have wired up our Reset button to our newly created function. Go ahead and click Reset and see the data populated in your Firebase dashboard.

firebase-dashboard-times

Now that we have our information, we need to display it in our application. First though, we have to bind the data we got from Firebase to an Angular object. There are two main ways we can sync data: three-way data-binding and array pushing.

For this demo, we want the object to be immediately synchronized, so we will be using three-way data-binding. The array way is used more for things that don’t need immediate syncing like a real-time chat application. Items (messages) are only synced when a user clicks “Send”.

We will use the three-way data-binding method for this application. First, we will need to sync the information from our database to an Angular variable.

Syncing Objects

To get objects synced as an object in Angular, we can do the following:

// create our angular module and inject firebase
angular.module('scheduleApp', ['firebase'])

// create our main controller and get access to firebase
.controller('mainController', function($scope, $firebase) {
  
  // connect to firebase 
  var ref = new Firebase("https://burning-torch-4263.firebaseio.com/days");  
  var fb = $firebase(ref);

  // sync as object 
  var syncObject = fb.$asObject();
  
});

We now have all the data in JSON form in that syncObject variable.

The final part to getting three way data-binding (between our Angular, front-end view, and Firebase), is to use the $bindTo function on our syncObject.

Three Way Data Binding

The following is the code to get the information from our database into a $scope variable.

// create our angular module and inject firebase
angular.module('scheduleApp', ['firebase'])

// create our main controller and get access to firebase
.controller('mainController', function($scope, $firebase) {
  
  // connect to firebase 
  var ref = new Firebase("https://burning-torch-4263.firebaseio.com/days");  
  var fb = $firebase(ref);

  // sync as object 
  var syncObject = fb.$asObject();

  // three way data binding
  syncObject.$bindTo($scope, 'days');
  
});

What is great about this is that the code is so simple to get information from Firebase and have it synced across not just our own computer, but across every person connected at that time.

We have real-time data-syncing now!

This won’t do us too much good yet though since we don’t have our application wired up to show the data from this new $scope variable.

We can go into the HTML file and type {{ days }} and you will see the information that we created earlier in the reset() function be pulled from Firebase and shown in our view.

Let’s use Angular’s ng-repeat to loop through this object and display our days and time slots.

Displaying Dynamic Days and Time Slots

In our index.html file where we placed our filler data for the day and time slot, we’ll update it with Angular data from our bound $scope object.

Here’s the updated HTML for that:

<div class="row times">
    
  <div class="col-xs-4 text-center" ng-repeat="day in days">
            
    <h2>{{ day.name }}</h2>
    
    <div class="time-slot" ng-repeat="slot in day.slots">     

      <input type="checkbox" id="{{ day.name }}-{{ $index }}" ng-model="slot.booked" ng-disabled="slot.booked">

      <label for="{{ day.name }}-{{ $index }}">{{ slot.time }}<br>
        <span ng-if="slot.booked">Booked</span>
        <span ng-if="!slot.booked">Available</span>
      </label>

    </div>
  </div>       
    
</div>

We are looping over the object we bound earlier to $scope.days. By using ng-repeat twice, we can loop over the days and each days time slots.

We are also setting a checkbox like we did earlier so that the ng-model will update from false to true when it is checked.

We will use ng-disabled to disable the checkbox after it has been booked and also ng-if to show the word Booked or Available.

Synchronizing Booked Time Slots

This is where the magic trick happens: Everything is already wired to work! Since the object was three-way bound, if you click a checkbox, then it will automatically update on all clients viewing the site and on Firebase!

Conclusion

As real-time applications are becoming more prominent, a service like Firebase is great since it handles a lot of the application details for you. Front-end developers can have a solid backend and infrastructure in Firebase and just worry about designing the front-end.

Firebase is a fun service and I’d encourage everyone to take a look at it and build something cool.

Chris Sevilleja

Co-founder of Scotch.io. Slapping the keyboard until something good happens.