Angular MVVC ASP.NET Core Firebase angularfire2
▌Introduction
▋Related articles
[ASP.NET Core X Angular] (1) – Hello world!
[ASP.NET Core X Angular] (2) – Routing
[ASP.NET Core X Angular] (3) – Sub component (input & emit)
▌Environment
▋Visual Studio 2015
Update 3
▋NPM: 3.10.3
▋Microsoft.AspNetCore.Mvc
1.0.0
▋angular 2: 2.1.0
▋angularfire2 : 2.0.0-beta.6
▌Firebase
Firebase* is a NoSql cloud databse, create a new project
and enable read and write permission before we start implementing authorization.
{
"rules": {
".read": true,
".write": true
}
}
|
▋Install angularfire2
$>npm install angularfire2 ––save
$>npm install firebase ––save
|
PS. Since angularfire2 is in beta, it doesn’t support “Storage”
api so far. However, we can still use firebase official js library to
develop the functions.
Optional: If you develop with Angular CLI and want to
deploy the website to firebase, in stall firebase-tools as well.
Then you should update systemjs.config.js to include the packages.
▌Integrate Firebase database
We will update the sample codes in [ASP.NET X Angular2](7) –
Sub-routing, which contains the constant products’ data in memory
not in database.
Our goal is making the product.service support CRUD functions
for data in Firebase.
▋Firebase configuration
Create a FirebaseConfig module to store the api key and other necessary information
for connecting to firebase.
PS. You can find your api key
in Firebase by clicking the icon below.
▋FirebaseConfig.ts
export module FirebaseConfig
{
var config: any;
export function Get() {
config =
{
apiKey: "XXXXXXXXXXXX",
authDomain: "xxxx.firebaseapp.com",
databaseURL: "https://xxxx.firebaseio.com",
storageBucket: "xxxxx.appspot.com",
messagingSenderId: "XXXXXXXXXXX"
};
return config;
}
}
|
▋product.app.module.ts
Inject the angularfire2
package and api key config in to product.app.module.ts
//...
import { AngularFireModule }
from 'angularfire2';
import {FirebaseConfig} from '../../class/FirebaseConfig';
@NgModule({
imports: [
BrowserModule,
FormsModule,
HttpModule,
ProductRoutes,
AngularFireModule.initializeApp(FirebaseConfig.Get())
],
declarations:
[
//...
],
bootstrap:
[ProductAppComponent]
})
export class ProductAppModule { }
|
▋Update product.service with Firebase integration
Now we are going to update
product.service to get the data from Firebase.
Tips:
Notice that everything in
Firebase is a URL, so if the database structure is like this,
Get the entire products:
constructor(private af: AngularFire) {}
this.af.database.object('/Demo/products');
|
Get the first object with
key:
this.af.database.object('/Demo/products/0');
|
Okay, let’s update our
Service to integrate Firebase real-time data.
▋product.service.ts
//...
import { AngularFire,
FirebaseListObservable } from 'angularfire2';
@Injectable()
export class ProductService {
constructor(private af: AngularFire) {}
//Create
public create(prod:Product){
return new Promise(
resolve => {
let itemObservable = this.af.database.object('/Demo/products/' + prod.Id);
itemObservable.set(prod); //Set will overwrite
resolve();
});
}
//Update
public update(prod: Product)
{
return new Promise<Product>(
resolve => {
let itemObservable = this.af.database.object('/Demo/products/' + prod.Id);
itemObservable.update(prod);
//Update current data
resolve();
})
};
//Remove
public remove(prod: Product)
{
return new Promise(
resolve => {
let itemObservable = this.af.database.object('/Demo/products/' + prod.Id);
itemObservable.remove(); //Remove current data
resolve();
})
};
//Get data with key
public get(key: string) {
return new
Promise<Product>(
resolve => {
this.af.database.object('/Demo/products/' + key).subscribe(data => {
resolve(data);
})
});
}
//Get books (or toys/music)
public getBooks() {
return new
Promise<Product[]>(
resolve => {
this._queryProducts().subscribe(data
=> {
if (data) {
let books = data.filter(x => x.Type == "Book");
resolve(books);
}
else {
resolve([]);
}
})
});
}
//Query data from firebase
private _queryProducts() {
return this.af.database.object('/Demo/products');
}
}
|
Notice that we
could use “retrieving-data-as-objects” way in the above codes, or either use “retrieving-data-as-lists” way to complete the same functions.
▋Demo
▌Integrate Firebase
authentication
Remember that in the
beginning we set both “read” and “write” are PUBLIC with the database.
Now try set the rules as “must-be-authorized”,
{
"rules": {
".read": "auth != null",
".write": "auth != null"
}
}
|
And you will get the error message
like this…
EXCEPTION: permission_denied at /Demo/products: Client doesn't
have permission to access the desired data.
So in the next step, we have
to create a login and authorization page for Firebase and make sure the
authorized user could have the permission to read/write the database.
▋Enable OAuth provider
We will use Google OAuth for example, make sure the
Google Authentication provider is enabled
in your Firebase console.
▋Enable OAuth provider
We will put the login/logout functions on the below
app.component.
If the user already logins, show the user’s information
and logout button on the page.
▋app.component.html
<div class="card">
<div class="card-block">
<div class="card-text" [ngSwitch]="isAuth">
<div *ngSwitchCase="false" class="text-center">
<button class="btn btn-toolbar" (click)="login('google')">
<img width="30" src="../asset/images/logo/google-logo.png" />
Use Google Account
</button>
</div>
<div *ngSwitchCase="true" class="text-center">
<table class="table">
<tr>
<td class="text-center">
<label class="control-label">{{user.name}}</label>
</td>
</tr>
<tr>
<td class="text-center">
<label class="control-label">{{user.email || '(no email)'}}</label>
</td>
</tr>
</table>
<div>
<input type="button" class="btn btn-warning" (click)="logout()" value="Logout" />
</div>
</div>
</div>
</div>
</div>
|
The HTML should be displayed like this.
▋app.component.ts
Here are the login/logout functions, notice that we check
the user’s login state in constructor.
/// <reference
path="../lib-npm/typings/jsnlog.d.ts" />
import { Component, OnInit }
from '@angular/core';
import { AngularFire, AuthProviders,
AuthMethods } from 'angularfire2';
@Component({
selector: 'core-app',
templateUrl:'/app/app.component.html'
})
export class AppComponent implements OnInit {
private isAuth = false;
private user = {};
constructor(private af:
AngularFire) {
//Check the login state
this.af.auth.subscribe(
user
=> this._changeState(user),
error
=> JL("Angular2").error(error)
);
}
ngOnInit() {
}
//Login
private login(provider:
string) {
this.af.auth.login({
provider: this._getProvider(provider),
method: AuthMethods.Popup
});
}
//Logout
private logout() {
this.af.auth.logout();
}
//Check if the user is login or not
private _changeState(user:
any = null) {
if (user) {
this.isAuth = true;
this.user = this._getUserInfo(user)
}
else {
this.isAuth = false;
this.user = {};
}
}
//Get the user information from Provider's user data
private _getUserInfo(user:
any): any {
if (!user) {
return {};
}
let data = user.auth.providerData[0];
return {
name:
data.displayName,
avatar: data.photoURL,
email: data.email,
provider: data.providerId
};
}
private
_getProvider(provider: string) {
switch (provider) {
case 'twitter': return
AuthProviders.Twitter;
case 'facebook': return AuthProviders.Facebook;
case 'github': return AuthProviders.Github;
case 'google': return AuthProviders.Google;
}
}
}
|
▋app.module.ts
Of course we have to import the necessary AngularFireModule, AuthProviders, AuthMethods and also initialize AngularFireModule
in app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { AngularFireModule, AuthProviders, AuthMethods
} from 'angularfire2';
import
{FirebaseConfig} from './class/FirebaseConfig';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(FirebaseConfig.Get())
],
declarations:
[AppComponent],
bootstrap:
[AppComponent]
})
export class AppModule { }
|
沒有留言:
張貼留言