angular / angularfire

Angular + Firebase = ❤️
https://firebaseopensource.com/projects/angular/angularfire2
MIT License
7.69k stars 2.19k forks source link

Configuring Ionic2/AngularFire2 and Auth #691

Closed mukesh51 closed 7 years ago

mukesh51 commented 7 years ago

Version info

Angular: 2.1.1

Firebase: ^3.6.1

AngularFire: ^2.0.0-beta.6

Other (e.g. Ionic/Cordova, Node, browser, operating system): ionic 2.1.12, corodova 6..4.0

How to reproduce these conditions

This is a document to help individuals who are having issues in configuring AngularFire2 in general and AngularFire2 Auth.

Failing test unit, Plunkr, or JSFiddle demonstrating the problem N/A

Steps to set up and reproduce N/A

Sample data and security rules N/A

<-- include/attach/link to some json sample data (or provide credentials to a sanitized, test Firebase project) -->

Debug output

Errors in the JavaScript console N/A

Output from firebase.database().enableLogging(true); N/A

Screenshots N/A

Expected behavior N/A. This is more of a tutorial

Actual behavior N/A

There have been few issues reported around integration of angularFire2 with Ionic2. So thought of sharing this, so that it helps people getting started. The below setup have been executed on Windows 10, but it should be same for Mac and Linux.

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

Prerequisites The first step is to ensure you've latest version of node installed. If not, you can get it installed from here. This will install both node and npm.

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

c:\projects>node -v
v6.9.1 

As of now, this is the most stable version. If you're not on this version, please upgrade yourself to latest version by installing node from here.

Check your npm version by executing the following command.

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.

C:\projects>npm install -g cordova

C:\projects>npm install -g ionic

Once the above commands are successful, check the versions of corodva and ionic by executing the following commands.

C:\projects>cordova -v
6.4.0
C:\projects>ionic -v
2.1.8

Once the above commands are executed, you're all set to create your Ionic 2 app. To create your app, change into the directory where you want your app to reside and execute the following command

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

The command ionic start with create the "Ionic_AngularFire2_Project" using "blank" temlate. The --v2 flag ensures, this is a Ionic2 project.

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

C:\projects\Ionic_AngularFire2_Project>

To ensure your app is running, execute the following command

C:\projects\Ionic_AngularFire2_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 display the 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:

C:\projects\Ionic_AngularFire2_Project>npm install -g typings 
C:\projects\Ionic_AngularFire2_Project>npm install -g typescript

Check typings and typescript versions by executing following commands:

C:\projects\Ionic_AngularFire2_Project>typings -v
2.0.0
C:\projects\Ionic_AngularFire2_Project>tsc -v
Version 2.0.10

Configuring AngularFire2 and Firebase

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

C:\projects\Ionic_AngularFire2_Project>npm install angularfire2 firebase --save

This should add angularfire2 and firebase entry in your project's package.json file in dependencies section. Something similar

"angularfire2": "^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

yourapp.module.ts file should look something like this.


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 'angularfire2';

export const firebaseConfig = {
  apiKey: "xxxxxxxxxx",
  authDomain: "your-domain-name.firebaseapp.com",
  databaseURL: "https://your-domain-name.firebaseio.com",
  storageBucket: "your-domain-name.appspot.com",
};

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

Inject AngularFire and Bind it to List Now inject AngularFire in your component. Open your home.ts by going into src/pages/home/home.tsand make the following changes:

1)Import "AngularFire, FirebaseListObservable" at the top of your component. 2)Inject your AngularFire dependency in the constructor. 3)Call the list method on angularFire's database object.

Your home.ts file should look like this.

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

import { AngularFire, FirebaseListObservable } from 'angularfire2';

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

  items: FirebaseListObservable<any[]>;

  constructor(public navCtrl: NavController,af: AngularFire) {
    this.items = af.database.list('/items');
  }

}

Update yourhome.html at src/pages/home/home.html, with following entry

<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

C:\projects\Ionic_AngularFire2_Project> ionic serve

This should fetch you the data from firebase.

Configuring AngularFire2 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

C:\projects\Ionic_AngularFire2_Project> ionic g provider AuthService

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

import { Injectable } from '@angular/core';
import { AuthProviders, FirebaseAuth, FirebaseAuthState, AuthMethods } from 'angularfire2';

@Injectable()
export class AuthService {
  private authState: FirebaseAuthState;

  constructor(public auth$: FirebaseAuth) {
    this.authState = auth$.getAuth();
    auth$.subscribe((state: FirebaseAuthState) => {
      this.authState = state;
    });
  }

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

  signInWithFacebook(): firebase.Promise<FirebaseAuthState> {
    return this.auth$.login({
      provider: AuthProviders.Facebook,
      method: AuthMethods.Popup
    });
  }

  signOut(): void {
    this.auth$.logout();
  }

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

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

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 'angularfire2';
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",
};

@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

<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>

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

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

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

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

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

  items: FirebaseListObservable<any[]>;

  constructor(public navCtrl: NavController,af: AngularFire,private _auth: AuthService) {
    this.items = af.database.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 and once you're authenticated, you should see your Facebook display name in console. You can try redirecting yourself to another page to grab additional details.

Hope this helps.

Any Thoughts ?

WhatsThatItsPat commented 7 years ago

Isn't typings superfluous now?

mukesh51 commented 7 years ago

@patrickmcd :+1:

katowulf commented 7 years ago

Nice! ☃

tomaszczechowski commented 7 years ago

One comment on my end:

In home.ts rather than using AngularFire in order to fetch list of "items" I would recommend to refer directly to AngularFireDatabase:


...
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2';
...
export class HomePage {
  items: FirebaseListObservable<any[]>;

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

Anyway thanks for sharing, looks pretty same as mine implementation 😄

samedii commented 7 years ago

Posting this here as well since I couldn't get the above to work without this modification.

I had to add a custom rollup.config.js script (not sure every option here is actually needed):

plugins: [
  ...
  commonjs({
      include: [
        'node_modules/rxjs/**',
        'node_modules/angularfire2/**',
        'node_modules/moment/**',
        'node_modules/@ionic/storage/**'
      ],
      namedExports: {
        'node_modules/firebase/firebase.js': ['initializeApp', 'auth', 'database'],
        'node_modules/angularfire2/node_modules/firebase/firebase-browser.js': ['initializeApp', 'auth', 'database']
      }
  }),
...

from here https://forum.ionicframework.com/t/ionic-2-rc-0-and-firebase-not-angularfire/65018/7

Also have useStrict: false or else I get navigator undefined...

Note that you set where your custom config is in package.json with:

...
  "config": {
    "ionic_rollup": "./scripts/rollup.config.js"
  }
}

Hope this helps someone save some time

adirzoari commented 7 years ago

@mukesh51 I did exactly what you wrote I get this error while run in android emulator

EXCEPTION: Uncaught (in promise): ReferenceError: firebase is not defined

mukesh51 commented 7 years ago

@adirzoari I didn't receive this error, but try adding this line to home.ts

import * as firebase from 'firebase';

Also refer to issues #654 . Hope that helps. Also this issue is closed and you can refer to the tutorial here