AngularJS

What’s the Difference Between Ionic and AngularJS?



·

If you’re familiar with Ionic and Angular and the roles they play then the question posed in the title probably sounds a bit silly, but I quite often see questions like:

“Is PhoneGap better than Ionic?”

which don’t really make a lot of sense. PhoneGap and Ionic serve two completely different roles – Ionic is a framework for building mobile apps, and PhoneGap allows access to native device functionality and provides a native wrapper for an application – but these conceptual misunderstandings can do a lot to damage a beginners ability to grasp the framework.

In a similar sense to the PhoneGap question, it can be quite confusing for beginners to understand the relationship between Ionic and Angular (or even that there’s a relationship at all), especially if you started using Ionic first.

What I’m going to do in this tutorial is build the exact same functionality as I have in a tutorial for integrating email and Facebook login with Firebase in an Ionic application, but just with pure AngularJS and no Ionic at all (so we will be building a website rather than a mobile application in this tutorial, which is pretty rare for this blog!). Here’s what it will look like:

Angular Firebase Login Example

This should help provide some clarity as to how much of what you do with Ionic is actually AngularJS and which parts are Ionic. Basically, when using Ionic you’re actually building Angular applications, with a bunch of extra stuff added to make making mobile applications with Angular easier.

Getting Started with AngularJS

If you’re already using Ionic then you should have all the dependencies you need installed already, but if for some reason you do not have node and bower installed you should do that first.

Of course before you can start building with Angular you’re going to need to set up a few dependencies. The easiest way to do this is to clone the angular-seed project hosted on GitHub. This will set you up with a skeleton of a well structured Angular application, and also has templates for unit tests and end to end tests built in.

When looking at this example AngularJS project it might look a little bit intimidating, as there is a lot of files and folders that will look different to your normal Ionic applications. To be fair, the structure of the example application is overkill for what we will be doing. This structure is useful for complicated, production level applications so we could get away with a lot less, but I think it’s a good idea to get familiar with this structure anyway.

The only thing we’re really interested in at this stage is the app folder. Like with an Ionic application, we have an app.js file (and the contents should look comfortably familiar) and an index.html file, but the structure of the views is a little different.

Angular Folder Structure

Image from: johnpapa.net

Most tutorials you will see on Ionic have all of the views stored in a templates folder and all of the controllers either in a controllers folder or a single controllers.js file (left) – you could just as easily do that for this Angular project too if you like. But the default structure of the example application has a separate folder for each view, and stores all of the code needed for that view (the controller and the template file) in that folder (right). This makes no difference to how the application functions, but it is typically a better structure for larger applications as it organises your code by feature (which will make it easier to maintain as your application grows). You can also use this structure (or any other structure you want to use) in your Ionic applications too, I’ve touched on the differences between these two approaches in this tutorial if you’d like to look into it further.

Ok, let’s jump into getting our Angular project set up.

Setting up an AngularJS Project

First we will clone the angular-seed project into a new folder, and we’re going to add a little bit extra to the clone command so that we only pull in the latest code and not the entire commit history.

Run the following command to clone the angular-seed project:

git clone --depth=1 https://github.com/angular/angular-seed.git angular-firebase-login

Make the new project your current working directory:

cd angular-firebase-login

Run the following command to install the dependencies for AngularJS:

npm install

You should now have everything you need set up for a basic Angular application, but to run an Angular application you need to do it through a web server (just like you do when using Ionic). When using Ionic we can use the ionic serve command that the Ionic CLI provides, but since we’re not using Ionic in this project we can’t use any of the Ionic CLI tools. Fortunately, the angular-seed project comes with a simple web server built in, so you just need to run one simple command.

Run the following command to run your application

npm start

View your application by going to the following address:

http://localhost:8000/app/index.html

You should see a page like this:

Angular Seed Example

The angular-seed project has two views set up by default and provides a menu to switch between them. It also has a bunch of other fancy stuff set up like a version number that gets injected into the page, but we’re going to be ignoring everything but the basics for this tutorial.

Set up Bootstrap and Angular UI Bootstrap

You’ve probably already heard of the Bootstrap CSS Framework, we’re going to be using this to help with the UI of the application. Adding Bootstrap or any other CSS framework like Foundation to an AngularJS application is similar to what we do when we add Ionic to an AngularJS application. Ionic does quite a bit more than these CSS frameworks do, but the idea is basically the same.

As well as setting up Bootstrap we are also going to install Angular UI Bootstrap which provides a set of AngularJS directives which are based on Boostrap and removes the dependency on jQuery and Bootstraps own JavaScript.

Download Bootstrap into your project by running the following command:

bower install bootstrap

Download Angular UI Bootstrap into your project by running the following command:

bower install angular-bootstrap

Before you can make use of these you will also need to reference the appropriate files in your project.

Modify your index.html file to reflect the following:

  <meta name="description" content="">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
  <script src="bower_components/angular/angular.js"></script>
  <script src="bower_components/angular-route/angular-route.js"></script>
  <script src="bower_components/angular-bootstrap/ui-bootstrap.js"></script>

and you will also need to inject the dependency into your angular module.

Modify the following code in app.js to reflect the following:

angular.module('myApp', [
  'ngRoute',
  'ui.bootstrap',
  'myApp.view1',
  'myApp.view2',
  'myApp.version'
])

This is the same way that we would inject Ionic into an Angular application. Now both Bootstrap and Angular UI Bootstrap will be available in the project.

Set up a Basic Bootstrap Template

Let’s make use of Bootstrap now by setting up a simple Bootstrap template. Bootstrap is a very popular CSS framework so naturally there are a lot of resources out there, and you can find a bunch of free themes at startbootstrap.com. We’re going to be implementing this landing page theme so go ahead and download that.

This theme has a bunch of boiler plate content that we won’t be using, we will just be replacing the header with a login form, but it makes the page look a lot nicer and gives you an idea of how you would go about creating a layout in Angular if you haven’t already before (again, it’s very similar to what we would usually do in Ionic, we’re just lacking the Ionic directives like and so on).

We’re only going to have one page in this example, so you can remove the menu and we also want to get rid of the version string.

Remove the menu and version string from index.html*, just leaving the **ng-view div:

<div ng-view></div>

This ng-view operates similarly to Ionic’s ion-nav-view, basically it will inject the template of whatever view we are looking at between these tags. Now let’s set up the CSS for the template we downloaded

Create a new folder at app/css and move the landing-page.css file from the theme here as well as the app.css file your project already has.

Add the following references to the head section of your index.html

  <link rel="stylesheet" href="css/landing-page.css">
  <link rel="stylesheet" href="css/app.css">

Now we just need to place the HTML for the theme in the template for our view. We will use view1.html for this purpose and just ignore view2.html.

Replace the code in view1.html with the following:

    <!-- Navigation -->
    <nav class="navbar navbar-default navbar-fixed-top topnav" role="navigation">
        <div class="container topnav">
            <!-- Brand and toggle get grouped for better mobile display -->
            <div class="navbar-header">
                <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
                    <span class="sr-only">Toggle navigation</span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                    <span class="icon-bar"></span>
                </button>
                <a class="navbar-brand topnav" href="#">Start Bootstrap</a>
            </div>
            <!-- Collect the nav links, forms, and other content for toggling -->
            <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
                <ul class="nav navbar-nav navbar-right">
                    <li>
                        <a href="#about">About</a>
                    </li>
                    <li>
                        <a href="#services">Services</a>
                    </li>
                    <li>
                        <a href="#contact">Contact</a>
                    </li>
                </ul>
            </div>
            <!-- /.navbar-collapse -->
        </div>
        <!-- /.container -->
    </nav>


    <!-- Header -->
    <a name="about"></a>
    <div class="intro-header">
        <div class="container">

            <div class="row">
                <div class="col-lg-12">
                    <div class="intro-message">
the login form will go here
                    </div>
                </div>
            </div>

        </div>
        <!-- /.container -->

    </div>
    <!-- /.intro-header -->

    <!-- Page Content -->

	<a  name="services"></a>
    <div class="content-section-a">

        <div class="container">
            <div class="row">
                <div class="col-lg-5 col-sm-6">
                    <hr class="section-heading-spacer">
                    <div class="clearfix"></div>
                    <h2 class="section-heading">Death to the Stock Photo:<br>Special Thanks</h2>
                    <p class="lead">A special thanks to <a target="_blank" href="http://join.deathtothestockphoto.com/">Death to the Stock Photo</a> for providing the photographs that you see in this template. Visit their website to become a member.</p>
                </div>
                <div class="col-lg-5 col-lg-offset-2 col-sm-6">
                    <img class="img-responsive" src="img/ipad.png" alt="">
                </div>
            </div>

        </div>
        <!-- /.container -->

    </div>
    <!-- /.content-section-a -->

    <div class="content-section-b">

        <div class="container">

            <div class="row">
                <div class="col-lg-5 col-lg-offset-1 col-sm-push-6  col-sm-6">
                    <hr class="section-heading-spacer">
                    <div class="clearfix"></div>
                    <h2 class="section-heading">3D Device Mockups<br>by PSDCovers</h2>
                    <p class="lead">Turn your 2D designs into high quality, 3D product shots in seconds using free Photoshop actions by <a target="_blank" href="http://www.psdcovers.com/">PSDCovers</a>! Visit their website to download some of their awesome, free photoshop actions!</p>
                </div>
                <div class="col-lg-5 col-sm-pull-6  col-sm-6">
                    <img class="img-responsive" src="img/dog.png" alt="">
                </div>
            </div>

        </div>
        <!-- /.container -->

    </div>
    <!-- /.content-section-b -->

    <div class="content-section-a">

        <div class="container">

            <div class="row">
                <div class="col-lg-5 col-sm-6">
                    <hr class="section-heading-spacer">
                    <div class="clearfix"></div>
                    <h2 class="section-heading">Google Web Fonts and<br>Font Awesome Icons</h2>
                    <p class="lead">This template features the 'Lato' font, part of the <a target="_blank" href="http://www.google.com/fonts">Google Web Font library</a>, as well as <a target="_blank" href="http://fontawesome.io">icons from Font Awesome</a>.</p>
                </div>
                <div class="col-lg-5 col-lg-offset-2 col-sm-6">
                    <img class="img-responsive" src="img/phones.png" alt="">
                </div>
            </div>

        </div>
        <!-- /.container -->

    </div>
    <!-- /.content-section-a -->

	<a  name="contact"></a>
    <div class="banner">

        <div class="container">

            <div class="row">
                <div class="col-lg-6">
                    <h2>Connect to Start Bootstrap:</h2>
                </div>
                <div class="col-lg-6">
                    <ul class="list-inline banner-social-buttons">
                        <li>
                            <a href="https://twitter.com/SBootstrap" class="btn btn-default btn-lg"><i class="fa fa-twitter fa-fw"></i> <span class="network-name">Twitter</span></a>
                        </li>
                        <li>
                            <a href="https://github.com/IronSummitMedia/startbootstrap" class="btn btn-default btn-lg"><i class="fa fa-github fa-fw"></i> <span class="network-name">Github</span></a>
                        </li>
                        <li>
                            <a href="#" class="btn btn-default btn-lg"><i class="fa fa-linkedin fa-fw"></i> <span class="network-name">Linkedin</span></a>
                        </li>
                    </ul>
                </div>
            </div>

        </div>
        <!-- /.container -->

    </div>
    <!-- /.banner -->

    <!-- Footer -->
    <footer>
        <div class="container">
            <div class="row">
                <div class="col-lg-12">
                    <ul class="list-inline">
                        <li>
                            <a href="#">Home</a>
                        </li>
                        <li class="footer-menu-divider">&sdot;</li>
                        <li>
                            <a href="#about">About</a>
                        </li>
                        <li class="footer-menu-divider">&sdot;</li>
                        <li>
                            <a href="#services">Services</a>
                        </li>
                        <li class="footer-menu-divider">&sdot;</li>
                        <li>
                            <a href="#contact">Contact</a>
                        </li>
                    </ul>
                    <p class="copyright text-muted small">Copyright &copy; Your Company 2014. All Rights Reserved</p>
                </div>
            </div>
        </div>
    </footer>

Now you should be able to fire up your browser and see something like this:

Set up Firebase

As I mentioned before, we are going to be implementing the same functionality that is in this Ionic tutorial, with the exception of using the Cordova plugin for easier Facebook since we can only use that for mobile apps (we will use a normal OAuth popup instead).

You can literally copy and paste all of the Javascript code from that tutorial into this one and it will work, there is no difference in the Javascript files between Ionic and vanilla AngularJS, apart from the fact that Ionic provides some extra services that can be injected.

I’ll still step through how to integrate Firebase and implement the functionality in your Angular application here anyway, but for setting up your Firebase account if you haven’t already, just take a look at the Ionic tutorial.

IMPORTANT: It’s very important that you enable authentication in Firebase otherwise the next step will not work.

To make Firebase available in your Angular app you will need to first add a few things to your project.

Add the Firebase and Angular Fire scripts to index.html:

  <!-- Firebase -->
  <script src="https://cdn.firebase.com/js/client/2.2.4/firebase.js"></script>
  <!-- AngularFire -->
  <script src="https://cdn.firebase.com/libs/angularfire/1.1.2/angularfire.min.js"></script>

Firebase is the core Firebase library and Angular Fire is a specific AngularJS binding for Firebase.

Inject Firebase into your angular module:

angular.module('myApp', [
  'ngRoute',
  'ui.bootstrap',
  'firebase',
  'myApp.view1',
  'myApp.view2',
  'myApp.version'
]).

Set up the Login Form

Before we continue setting up the Firebase functionality for authentication, we need a login form that will allow our users to login, signup or login with Facebook. To keep this simple we are going to do all of this from the same form.

Add the following to view1.html where “the login form will go here” is currently:

                        <form class="login-form">
                            <div class="form-group">
                                <label for="email-input">Email address</label>
                                <input type="email" class="form-control" id="email-input" ng-model="data.email" placeholder="Email">
                            </div>
                            <div class="form-group">
                                <label for="password-input">Password</label>
                                <input type="password" class="form-control" id="password-input" ng-model="data.password" placeholder="Password">
                            </div>
                            <div class="form-group">
                                <button class="btn btn-primary" ng-click="loginFacebook()">Connect with Facebook</button>
                                <button class="btn btn-primary" ng-click="signupEmail()">Create Account</button>
                                <button class="btn btn-success" ng-click="loginEmail()">Log In</button>
                            </div>
                        </form>

Again, this is exactly the same as Ionic, we use ng-model to bind the fields to the controller and we use ng-click to trigger functions in the controller.

We’re going to add a bit of styling to this form as well to pretty it up

Add the following CSS to to app.css:

.login-form {
  background-color: #fff;
  padding: 3em;
  border-radius: 25px;
}

.login-form label {
  color: #000;
}

Set up Authentication

We’re going to be adding some code to the controller for view1 now to enable logging in, but first we are going to turn off strict dependency injection.

Modify view1.js so that it reflects the following:

angular.module('myApp.view1', ['ngRoute'])

.config(['$routeProvider', function($routeProvider) {
  $routeProvider.when('/view1', {
    templateUrl: 'view1/view1.html',
    controller: 'View1Ctrl'
  });
}])

.controller('View1Ctrl', function($scope) {


});

Strict mode is enabled by default in the angular-seed project, and that’s the reason it initially looked a little weird and different to what you would be used to doing with Ionic. You can use this same strict mode in Ionic as well, but most people don’t by default – the problem with this though is that when your application is minified dependency injection in Angular will break.

Basically, dependency injection is how componenets in AngularJS grab their dependencies (like how we inject $scope, or $someService into controllers). If you’re using the style of code I have above, then your $scope parameter might be minified to some other name and now Angular will have no idea what to load. However, you can code in this “non strict” mode and still minify your applications – check out my tutorial on how to minify an Ionic application and prevent dependency injection breaking.

If you’re interested in reading more about this topic and the magic of AngularJS dependency injection, then you should take a look at this blog post by Alex Rothenberg.

Now let’s drop in the code to handle the logins.

Add the following code to View1Ctrl in view1.js:

.controller('View1Ctrl', function($scope) {

    $scope.signupEmail = function(){  

      var ref = new Firebase("https://<YOUR-FIREBASE-APP-ID>.firebaseio.com");

      ref.createUser({
        email    : $scope.data.email,
        password : $scope.data.password
      }, function(error, userData) {
        if (error) {
          console.log("Error creating user:", error);
        } else {
          console.log("Successfully created user account with uid:", userData.uid);
        }
      });

    };

    $scope.loginEmail = function(){

      var ref = new Firebase("https://<YOUR-FIREBASE-APP-ID>.firebaseio.com");

      ref.authWithPassword({
        email    : $scope.data.email,
        password : $scope.data.password
      }, function(error, authData) {
        if (error) {
          console.log("Login Failed!", error);
        } else {
          console.log("Authenticated successfully with payload:", authData);
        }
      });

    };

    $scope.loginFacebook = function(){

        var ref = new Firebase("https://<YOUR-FIREBASE-APP-ID>.firebaseio.com");

        ref.authWithOAuthPopup("facebook", function(error, authData) {
          if (error) {
            console.log("Login Failed!", error);
          } else {
            console.log("Authenticated successfully with payload:", authData);
          }
        });

    };

});

Make sure to replace with your own App ID from Firebase. Once you’ve done that you should be able to launch your application and create accounts, sign in to those accounts and log in with Facebook. Nothing happens after authentication right now, but if you pull up the console you should be able to see successful requests being made.

Angular Firebase Login Example

BONUS CONTENT: Download the source code for this example application:

Summary

As you can see from this tutorial, and if you’ve had a look at the same tutorial for Ionic, building something with pure AngularJS is not all that different to building it with Ionic. To drive the point home, that is because an Ionic app is an Angular app, just with a bunch of extra stuff added for mobile.

The great thing is if you started with Ionic then you should pretty easily be able to translate those skills into building normal web applications with AngularJS, and vice versa if you already know Angular then you should be able to pick up Ionic very quickly.

What to watch next...