# Using AngularFire with Ionic 2

This document provides you a walkthrough of integrating AngularFire Authentication with Ionic2.
The below setup has been tested on Windows 10, but it should be same for Mac/Linux.

Ensure that you're executing these commands as **Administrator** on Windows and **sudo** on Mac/Linux to avoid any errors.

### Prerequisites
The first step is to ensure you've latest version of **Node** installed.
You can get the latest version from [here](https://nodejs.org).
This will install both node and npm.

After installing node, check the version by executing the following command in your prompt window.

```bash

C:\projects>node -v
v6.9.1

```

As of writing this document, this is the most stable version. If you're not on this version,
please upgrade yourself to latest version by installing node from [here](https://nodejs.org).

Check your npm version by executing the following command.

```bash

C:\projects>npm -v
3.10.8

```

**_Your Application code sits on top of Ionic Framework and the Ionic Framework sits on top of Cordova._**

Let's get them installed globally, so that all projects can use them.

Execute the following commands.

```bash

C:\projects>npm install -g cordova

C:\projects>npm install -g ionic

```

Once the above commands are executed successfully, Check the versions of cordova and ionic by executing the following commands.

```bash

C:\projects>cordova -v
6.4.0

C:\projects>ionic -v
2.1.8

```

These are the latest versions as of writting this document.

On successful execution of above commands, you're all set to create your Ionic app.
To create your app, change into the directory where you want your app to reside and execute the following command

```bash

C:\projects> ionic start Ionic_AngularFire_Project blank --v2

```

>The command ionic start will create the project with name "Ionic_AngularFire_Project" using "blank" template.

>The --v2 flag ensures, this is a Ionic2 project.

Change to the project directory, which was just created with above command

>C:\projects\Ionic_AngularFire_Project>

To start your app, execute the following command

```bash

C:\projects\Ionic_AngularFire_Project> ionic serve

```

If everything is installed correctly, the app should open your browser with the dev server running at following url
**`http://localhost:8100`** and will display default home page.

Stop you server by pressing "ctrl + c", if it is still running from the above step and
install typings and typescript globally by executing the following commands:

**Note:-** typings is not required for our current application to work, but it will be helpful incase you want to bring in
external libraries and extend this application.

```bash

C:\projects\Ionic_AngularFire_Project>npm install -g typings

C:\projects\Ionic_AngularFire_Project>npm install -g typescript

```

Check typings and typescript versions by executing following commands:

```bash

C:\projects\Ionic_AngularFire_Project>typings -v
2.0.0

C:\projects\Ionic_AngularFire_Project>tsc -v
Version 2.0.10

```

### Configuring AngularFire and Firebase

Install AngularFire and firebase by executing the following command in your project directory

```ts

C:\projects\Ionic_AngularFire_Project>npm install AngularFire firebase --save

```

_This should add AngularFire and firebase entry in your project's package.json file in dependencies section. Something similar_

>"AngularFire": "^2.0.0-beta.6",

>"firebase": "^3.6.1",

### Setup @NgModule

Open your project in your favourite editor and open the `app.module.ts` file, under `src/app`
and add the following three entries.

>1) Import AngularFireModule at top.

>2) Define your firebaseConfig constant.

>3) Initialize your app, by calling it in the "imports" array in @NgModule

your `app.module.ts` file should look something like this.

```ts

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { AngularFireModule } from 'AngularFire';

export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
  messagingSenderId: '<your-messaging-sender-id>'
};

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: []
})
export class AppModule { }

```
### Inject AngularFireDatabase and Bind it to List

Now inject AngularFireDatabase in your component. Open your `home.ts` by going into `src/pages/home/home.ts` and make the following changes:

>1) Import "AngularFireDatabase, FirebaseListObservable" at the top of your component.

>2) Inject your AngularFireDatabase dependency in the constructor.

>3) Call the list method on the AngularFireDatabase service.

Your `home.ts` file should look like this.

```ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AngularFireDatabase, FirebaseListObservable } from 'AngularFire/database';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  items: FirebaseListObservable<any[]>;

  constructor(public navCtrl: NavController, db: AngularFireDatabase) {
    this.items = db.list('/items');
  }

}

```

**Update** your `home.html` at `src/pages/home/home.html`, with following entry

```html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
  <ion-item class="text" *ngFor="let item of items | async">
    {{item.$value}}
  </ion-item>
  </ion-list>
</ion-content>

```

** Run your app by executing the following command **

```bash

C:\projects\Ionic_AngularFire_Project> ionic serve

```

This should fetch the data from firebase.

## Configuring AngularFire Auth with Ionic2

Continuing with the above example stop your server by pressing `ctrl+c` and go to command prompt and
generate a service by executing the following command

```bash

C:\projects\Ionic_AngularFire_Project> ionic g provider AuthService

```

This should create the AuthService under `src/providers/auth-service.ts`.
Update the service with the following code.

```typescript
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { AngularFireAuth } from 'AngularFire/auth';
// Do not import from 'firebase' as you'll lose the tree shaking benefits
import firebase from 'firebase/app';

@Injectable()
export class AuthService {
  private currentUser: firebase.User;

  constructor(public afAuth: AngularFireAuth) {
    afAuth.authState.subscribe((user: firebase.User) => this.currentUser = user);
  }

  get authenticated(): boolean {
    return this.currentUser !== null;
  }

  signInWithFacebook(): firebase.Promise<any> {
    return this.afAuth.auth.signInWithPopup(new firebase.auth.FacebookAuthProvider());
  }

  signOut(): void {
    this.afAuth.auth.signOut();
  }

  displayName(): string {
    if (this.currentUser !== null) {
      return this.currentUser.facebook.displayName;
    } else {
      return '';
    }
  }
}

```

Add your service in `app.module.ts`. Your `app.module.ts` should look like this

```ts

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';

import { AngularFireModule } from 'AngularFire';
import { AuthService } from '../providers/auth-service';


export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
  messagingSenderId: '<your-messaging-sender-id>'
};

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp),
    AngularFireModule.initializeApp(firebaseConfig)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [AuthService]
})
export class AppModule { }

```

Update your `home.html` to add a login button. Your `home.html` should look like this

```html

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Blank
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>
  <ion-list>
  <ion-item class="text" *ngFor="let item of items | async">
    {{item | json}}
  </ion-item>
  </ion-list>

  <button ion-button outline (click)="signInWithFacebook()">Facebook</button>
</ion-content>

```

and finally, add the corresponding click handlers in `home.ts` as follows.
Also, ensure the *AuthService* is injected in the constructor. Your `home.ts` should look like this

```ts

import { Component } from '@angular/core';
import { NavController } from 'ionic-angular';

import { AuthService } from '../../providers/auth-service';
import { AngularFireDatabase, FirebaseListObservable } from 'AngularFire/database';

@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

  items: FirebaseListObservable<any[]>;

  constructor(public navCtrl: NavController, db: AngularFireDatabase, private _auth: AuthService) {
    this.items = db.list('/items');
  }

  signInWithFacebook(): void {
    this._auth.signInWithFacebook()
      .then(() => this.onSignInSuccess());
  }

  private onSignInSuccess(): void {
    console.log("Facebook display name ",this._auth.displayName());
  }

}

```

Now run your app and if everything is configured correctly, you should be able to click on the login button in your app,
which should open the facebook pop-up.

Once you authenticate yourself, you should see your Facebook display name in console.

You can try redirecting yourself to another page to grab additional details from Facebook.


***Running our application on mobile phone.***

Ensure you've the platform added to your project. If not add the platform by executing the following command.

```

C:\projects\Ionic_AngularFire_Project>ionic platform add android

```

This adds android platform for your project.
Replace android with ios, if you're on Mac book or add both. The generic command is ```ionic platform add <platform-name>```

Now, let's try to run the app in browser. Execute the command

```

C:\projects\Ionic_AngularFire_Project> ionic run android

```

This should run the app on your mobile phone. Now click on the Facebook button and you'll notice the button doesn't work anymore.
This is because the code written so far is good for running our application in browsers, but when running the application on mobile phones, we need to have access to ***Native Mobile API's***, which are provided by _Cordova Plugins_.

**We can access these cordova plugins, using Ionic Native, which are nothing but wrappers for cordova plugins.**

List of all Ionic Native API's for cordova plugins can be found [here](http://ionicframework.com/docs/v2/native/).

Let's look at configuring and installing facebook plugin [here](http://ionicframework.com/docs/v2/native/facebook/).
_Ensure you follow the steps correctly to configure your app._

 Once you create your app and make a note of your App ID, go to command prompt in your project directory and execute the following command

 ```
 C:\projects\Ionic_AngularFire_Project>
 ionic plugin add cordova-plugin-facebook4 --save --variable APP_ID="123456789" --variable APP_NAME="myApp"

 ```

Replace App ID with your app id from portal and provide your app name.

This will install the cordova plugin for facebook.

Add the platform to your facebook portal as mentioned in the document [here](http://ionicframework.com/docs/v2/native/facebook/).

Now import the Platform and Facebook objects in your ```auth-service.ts```

```ts
import { Platform } from 'ionic-angular';
import { Facebook } from 'ionic-native';
```

and update the signInWithFacebook() method.

your ```auth-service.ts``` code should look like this.

```ts
import { Observable } from 'rxjs/Observable';
import { Injectable } from '@angular/core';
import { AngularFireAuth } from 'AngularFire/auth';
// Do not import from 'firebase' as you'll lose the tree shaking benefits
import firebase from 'firebase/app';

import { Platform } from 'ionic-angular';
import { Facebook } from 'ionic-native';

@Injectable()
export class AuthService {
  private currentUser: firebase.User;

  constructor(public afAuth: AngularFireAuth) {
    afAuth.authState.subscribe((user: firebase.User) => this.currentUser = user);
  }

  get authenticated(): boolean {
    return this.currentUser !== null;
  }

  signInWithFacebook(): firebase.Promise<any> {
    if (this.platform.is('cordova')) {
      return Facebook.login(['email', 'public_profile']).then(res => {
        const facebookCredential = firebase.auth.FacebookAuthProvider.credential(res.authResponse.accessToken);
        return this.afAuth.auth.signInWithCredential(facebookCredential);
      });
    } else {
      return this.afAuth.auth.signInWithPopup(new firebase.auth.FacebookAuthProvider());
    }

  }

  signOut(): void {
    this.afAuth.auth.signOut();
  }

  displayName(): string {
    if (this.currentUser !== null) {
      return this.currentUser.facebook.displayName;
    } else {
      return '';
    }
  }
}


```

Verfiy your app is running in browser by executing the following command

```

C:\projects\Ionic_AngularFire_Project>ionic serve

```

Everything should work. Now trying running the app on your android phone

```

C:\projects\Ionic_AngularFire_Project> ionic run android

```

Once the App launches click on the Facebook login button and it should open up the native facebook app for authentication and once your enter credentials and gets succesfully authenticated, it should redirect you back to the home page.
