How AngularDart & Firebase did an App together

Preview:

Citation preview

How

AngularDart & Firebase did an App together

Jana Moudra @Janamou #dfua

@Janamou

JavaScript, TypeScript, Dart, Elm,...

React, Angular, Ember.js, Preact, Vue.js, …

?

dartlang.org

For building Web browser, server, command line, and mobile apps

flutter.ioFlutter talk

Saturday, 10:10

For building Web browser, server, command line, and mobile apps

But hey, isn’t Dart dead?

NO

Sunday night...

Dart 2.0 is close...

Easy to learn

Optionally vs statically typed

Compiles to JavaScript

Tons of libraries in the SDK

main() {

print("Hello #DFUA 2017!");

}

// Is null no undefined

var sum;

// Tools warn you

int count = "Jana";

// Cascade operator

Dog dog = new Dog()

..name = "Andy"

..age = 8;

this is always this

no need to fix it!

+ =

webdev.dartlang.org/angular

? ?? ??

Google

is using it!

Jana Moudra @Janamou #dfua

$$$ at Google

AdWords, AdSense, AdMob

Millions of lines of code

25-100% increase in development speed

at Google

Componeeeeeents FTW!!!

Simple & reusable

Not only viewServices Router

Directives HTTP Pipes Forms Components Testing

Great apps need a backend!

NeededLots of implementation

Database, File Upload, User accounts, Anonymous user, OAuth,

Hosting ...

For a simple app...

Hello Firebase!

Realtime Database

Authentication

Cloud Storage

MessagingHosting... firebase.google.com

DEMO

TIME

Jana Moudra @Janamou #dfua

Include Js SDK

package:firebase

package:angular

+

<!DOCTYPE html>

<html>

<head>

<title>AngularDart + FB = ♥ demo</title> <meta charset="utf-8">

<script src="firebase.js"></script>

... imports for Dart scripts and others

</head>

<body>

<my-app>Loading...</my-app>

</body>

</html>index.html

->

index.html

<!DOCTYPE html>

<html>

<head>

<title>AngularDart + FB = ♥ demo</title> <meta charset="utf-8">

<script src="firebase.js"></script>

... imports for Dart scripts and others

</head>

<body>

<my-app>Loading...</my-app>

</body>

</html>

import 'package:angular/angular.dart';

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ]

)

class AppComponent {

// Here is the implementation

}

app_component.dart

app_component.dart

->

import 'package:angular/angular.dart';

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ]

)

class AppComponent {

// Here is the implementation

}

<div>

<layout-header></layout-header>

<main>

<div id="container">

<new-note></new-note>

<notes></notes>

</div>

<layout-footer></layout-footer>

</main>

</div>

app_component.html

app_component.html

->

<div>

<layout-header></layout-header>

<main>

<div id="container">

<new-note></new-note>

<notes></notes>

</div>

<layout-footer></layout-footer>

</main>

</div>

@Component(

selector: 'notes',

templateUrl: 'notes_component.html',

directives: const [CORE_DIRECTIVES])

class NotesComponent {

List<Note> notes = [];

// We need to retrieve notes somehow}

notes_component.dart

notes_component.dart

->

@Component(

selector: 'notes',

templateUrl: 'notes_component.html',

directives: const [CORE_DIRECTIVES])

class NotesComponent {

List<Note> notes = [];

// We need to retrieve notes somehow}

<div id="notes">

<div *ngFor="let note of notes">

<h3 *ngIf="note.title?.isNotEmpty">

{{note.title}}

</h3>

<div>

<p>{{note.text}}</p>

...

</div>

...

</div>

</div>notes_component.html

Sign in with Google

Read from realtime database

Save to realtime database

Upload to storage

import 'package:firebase/firebase.dart';

...

var provider = new GoogleAuthProvider();

try {

await auth().signInWithPopup(provider);

} catch (e) {

print('Error in sign in with Google: $e');

}

signInAnonymously()

signInWithEmailAndPassword(email, pass)

...

Structure the data{

"notes" : {

"-KUsbAq6445-ynO4lg6Z" : {

"img_url" : "dart.png",

"text" : "Is awesome!",

"title" : "Dart"

},

...

}

}

List<Note> notes = [];

DatabaseReference dbRef = database().ref("notes");

dbRef.onChildAdded.listen((e) {

DataSnapshot data = e.snapshot;

var val = data.val();

Note note = new Note(val["text"], ...);

notes.insert(0, note);

});

onValue onChildRemoved

onChildMoved onChildChanged

DatabaseReference dbRef = database().ref("notes");

try {

await dbRef

.push({"text": "New note!!!"})

.future;

} catch (e) {

print("Error in writing to database: $e");

}

StorageReference stRef = storage().ref("notes");

File file = ...;

try {

UploadTaskSnapshot snapshot = await stRef

.child(file.name)

.put(file)

.future;

// Get url in snapshot.downloadURL

} catch (e) {

print("Error in uploading to storage: $e");

}

Where should I put Firebase?

Component? Which?

Create a Service

import 'package:angular/angular.dart';

import 'package:firebase/firebase.dart';

...

@Injectable()

class FirebaseService {

List<Note> notes = [];

...

postItem(Note item) async { ... }

postItemImage(File file) async { ... }

signInWithGoogle() async { ... }

}firebase_service.dart

import 'firebase_service.dart';

...

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ],

providers: const [FirebaseService])

class AppComponent {

// Here is the implementation

}app_component.dart

->

import 'firebase_service.dart';

...

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ],

providers: const [FirebaseService])

class AppComponent {

// Here is the implementation

}app_component.dart

@Component(...)

class NotesComponent implements OnInit {

FirebaseService service;

List<Note> notes = [];

NotesComponent(this.service);

@override

ngOnInit() {

notes = service.notes;

}

}notes_component.dart

->

->

@Component(...)

class NotesComponent implements OnInit {

FirebaseService service;

List<Note> notes = [];

NotesComponent(this.service);

@override

ngOnInit() {

notes = service.notes;

}

}notes_component.dart

<div id="notes">

<div *ngFor="let note of notes">

<h3 *ngIf="note.title?.isNotEmpty">

{{note.title}}

</h3>

<div>

<p>{{note.text}}</p>

...

</div>

...

</div>

</div>notes_component.html

JavaScript

array

undefined

object functionnull

firebase.google.com/docs/reference

`

https://firebase.google.com/docs/reference/js/

@JS('firebase.app')

library firebase.app_interop;

import 'package:js/js.dart';

// Other imports...

package:js

firebase-dart/.../app_interop.dart

firebase-dart/.../app_interop.dart

@JS('App')

abstract class AppJsImpl {

external String get name;

external FirebaseOptions get options;

external AuthJsImpl auth();

external DatabaseJsImpl database();

external PromiseJsImpl delete();

external StorageJsImpl storage([String url]);

}

package:js

@JS('App')

abstract class AppJsImpl {

external String get name;

external FirebaseOptions get options;

external AuthJsImpl auth();

external DatabaseJsImpl database();

external PromiseJsImpl delete();

external StorageJsImpl storage([String url]);

}

firebase-dart/.../app_interop.dart

->

package:js

@JS('firebase.database')

library firebase.database_interop;

...

@JS('Database')

abstract class DatabaseJsImpl {

external AppJsImpl get app;

...

external ReferenceJsImpl ref([String path]);

...

}firebase-dart/.../database_interop.dart

package:js

Do I need to write this

manually?!TypeScript types definition file?

js_facade_gen library

Wrapper around interop

Dart types

package:firebase

// How we use the library

try { await childRef.remove();} catch (e) { print("Error while deleting item, $e");}

package:firebase

// Implementation in wrapper class

Future remove() => handleThenable(jsObject.remove());

Wrapper around interop

Dart types

Thenable to Future “magic”

package:firebase

Wrapper around interop

Allow-interop solved

// Implementation in wrapper class

bool forEach(action(DataSnapshot snapshot)) { var actionWrap = allowInterop((d) => action(...)); return jsObject.forEach(actionWrap);}

package:firebase

Wrapper around interop

Dart Map vs Js Objectnull, num, bool, String are okConversion through JSONFor Map or Iterable is js_util.dart

+ =

Productivity, performance, and stability

“Backend without implementing backend”

You can port any JavaScript library to Dart

Thank You! Questions?

Jana Moudra @Janamou #dfua