52
Firebase and ng2 Christoffer Noring Google Developer Expert Frontend Developer OVO Energy

Firebase ng2 zurich

Embed Size (px)

Citation preview

Firebase and ng2Christoffer Noring

Google Developer ExpertFrontend Developer OVO Energy

History

Founded in 2011 by Andrew Lee and James Tamplin

Started as a realtime database + API

Is now a full suite for app development

Aquired by Google in 2014

What is Firebase - now

Backend as a service in the cloud

3-way binding

2-way bindingview model

User changesview

Model changes

View is updated Model changed byan http call for example

3-way binding

view

model

view

model

User changes view

Model changes

Triggers synchronisation

Synchronizing

Application 1 Application 2

Model changes

View is updated

Liststhere can be only object

A normal list0 : item0

1 : item1

2 : item2

User deletes

0 : item1

1 : item2Index is reassigned

The problem with a list

in realtime0 : item01 : item12 : item2User 1 deletes

User 2 deletes3 : item3

4 : item4

We would have to reassign indexes constantlyIt would be error prone

A better way

-dfgf7687: item1-123niukzu : item2-dfsd4345 : item3-324dsvsd : item4

{

}

Unique indexes

NO recalculation of index

AngularFire

Lower level API

All Firebase featuresFeatures supported by AngularFire

Angular 1AngularFire

https://github.com/angular/angularfire2

Angular 2AngularFire2

$firebaseAuthworking with authentication

$firebaseObject working with object

$firebaseArray working with lists

AngularFire

AngularFire ( 1 )

AngularFireAuthworking with authentication

FirebaseObjectObservable

working with object

FirebaseListObservable

working with lists

AngularFire

AngularFire ( 2 )

Admin tools

Setup your project

Configure authentication / authorization

And much more

What can it do for us

Firebase console

Click here

Create/import Existing projects

Your database with collectionsData tab

Add to ng2 app

Configure from code

We need this configuration

var config = { apiKey: "", authDomain: "", databaseURL: "", storageBucket: "",};@NgModule({

imports: [ AngularFireModule.initializeApp( config, { //method: AuthMethods.Popup, method: AuthMethods.Redirect } ), BrowserModule ], declarations: [ AppComponent, Theater, MovieGoer

], bootstrap: [ AppComponent ]})

app.module.ts

add to import in root module

Add configuration to module

Inject AngularFire instance, where you want to use it

class Component{ constructor(af:AngularFire){

}}

import { AngularFire } from 'angularfire2';

this.af.database.list().<operation> .object().<operation>

access data

this.af.auth.<operation> authenticate

inject

Protect our app

The client is unsafe by definitionWe can protect our data with

AuthenticationAuthorization

Validation

AuthenticationAnonymous Username/password

OAuthCustom

Plenty of available methods

Enabled methods

2 Paste

Obtain1

3Github produces client secret/id

Firebase console

Programmatic AuthenticationAngularFireAuth

af.auth

.logout()this.af.auth.login({ provider: <provider>})

AuthProviders.Twitter

AuthProviders.Facebook

AuthProviders.Github

AuthProviders.Google

.getAuth().createUser()

.login()

Authorization

Rules tab

{ "rules": { ".read": "auth == null", ".write": "auth == null" }}

{ "rules": { ".read": "auth != null", ".write": "auth != null" }}

No authorization

Authorization enabled

read accesswrite access

Set rules per collection

{ "rules": { "foo": { ".read": true, ".write": false } }}

Collection

Authorization

Understanding rule evaluation{ "rules": { "foo": { “bar” : { ".read": true, ".write": false “child” :{ } } } }}

this.af.database.object('/foo')ACCESS DENIED

Permissions are cascaded but atomic

this.af.database.object(‘/foo/bar')

ACCESS GRANTEDthis.af.database.object(‘/foo/child’)

Summary authorisation

You can set read/write rules on Whole database

Per collection

Rules are appliedAtomicallyCascading

https://firebase.google.com/docs/database/security/securing-data#predefined_variables

Validation

We can stop erroneous data from entering our databaseWe can set validation rules

{ "rules": { "order": { “name” : { }, “quantity” : { } } }}

this.order = af.database.object('/order');this.order.set({ name : “some name”})

FAILS, must have ‘quantity’

Validate structure

".validate": "newData.isNumber() && newData.val() >= 0 && newData.val() <= 99"

{ "rules": { "order": { “name” : { }, “quantity” : {

} } }}

this.order = af.database.object('/order');this.order.set({ name : “some name”, quantity: 101})

FAILS, must be 0-99

Validate input data

Working with data

Object - Retrieve data

const relative = af.database.object('/item');Relative path

const absolute = af.database.object('https://<your-app>.firebaseio.com/item');Absolute path

@Component({ template : ` {{ ( item | async )?.name }} `})

async pipe, to unwrap value

export class AppComponent { item: FirebaseObjectObservable<any>; constructor(af: AngularFire) { this.item = af.database.object('/item'); }}

make connection

Object - Change data

const item = af.database.object('/item');

Destructive{ item : { abc : “123” }}

item.set({ prop : val })

Non Destructive{ item : { abc : “123” }}

item.update({ prop : val })

Data replaced{ item : { prop : val }}

Data amended{ item : { abc : “123”, prop : val }}

List - Retrieve data

Relative pathconst relative = af.database.list('/items');

Absolute pathconst absolute = af.database.list('https://<your-app>.firebaseio.com/items');

Queryconst queryList = af.database.list('/items', { query: { limitToLast: 10, orderByKey: true }});

List - Change data

const items = af.database.list('/items');

items.push( object ) Addupdate(keyRefOrSnap: string) Update item in listitems.remove( key:string ) Remove item in listitems.remove( ) Remove entire list

<li *ngFor="let item of items | async"> <input type="text" #updatetext [value]="item.text" /> <button (click)="updateItem(item.$key, updatetext.value)”>Update</button></li>

$key, $value

Respond to change

Every reference is an observable This is usually enough

Every action returns a promise For capturing auth errors and debug

const item = af.database.object('/item');item.subscribe( (data) => { console.log(‘something happened’) } )

Indicate change with css

var promise = item.set({ prop : newValue })promise.then( (data) = > { console.log(‘success’); }, (err) => { console.log(‘action failed for some reason’) } )

Indicate operation result

Data design best practices

Avoid nesting of data

{ foo : { bar : { something : { …… } } }}

32 levels are allowed, but don’t do it

You will get all child data, might be massive

Hard to keep track of access

Instead - shallow trees

{ orders : { orderid1 : { title : ‘some title’, timestamp : ‘fsdfsdfs’ }, orderid2 : { title : ‘some title’, timestamp : ‘fsdfsdfs’ } }}

Meta data { orderitems : { orderid1 : { orderitem_id_1 : { title : ‘tomato’, price : 5 }, orderitem_id_2 : { title : ‘cucumber’, price : 25 } }, orderid2 : { orderitem_id_3 : { title : ‘tomato’, price : 5 } } }}

Detailed data

Summary

AngularFire is a wrapper around Firebase APIAngularFire is for Angular1AngularFire2 is for Angular2

Simple API, list, object, auth

References are ObservablesActions are Promises

Firebase is backend as a service

Your data is protected by authentication, authorisation and validation

It is a platform - not just the database, use all of it

Thank you