1 of 70

How

AngularDart & Firebase

did an App together

Jana Moudra @Janamou #DevFestCZ

2 of 70

@Janamou

3 of 70

4 of 70

JavaScript, TypeScript, Dart, Elm,...

React, Angular, Ember.js,

Preact, Vue.js, …

?

5 of 70

6 of 70

7 of 70

For building

Web browser, server, command line, and mobile apps

dartlang.org

8 of 70

For building

Web browser, server, command line, and mobile apps

flutter.io

Flutter talk

Today, 10:00

9 of 70

10 of 70

But hey, isn’t Dart dead?

NO

11 of 70

Sunday night...

Dart 2.0 is almost here...

12 of 70

Easy to learn

Optionally vs statically typed

Compiles to JavaScript

Tons of libraries in the SDK

13 of 70

main() {

print("Hello #DevFestCZ 2017!");

}

14 of 70

// Is null no undefined

var sum;

// Tools warn you

int count = "Jana";

15 of 70

// Cascade operator

new Dog()

..name = "Andy"

..age = 8;

16 of 70

this is always this

no need to fix it!

17 of 70

18 of 70

+

=

webdev.dartlang.org/angular

?

?

?

?

?

19 of 70

Google

is using it!

@Janamou #DevFestCZ

20 of 70

at Google

$$$

21 of 70

at Google

AdWords, AdSense, AdMob

Millions of lines of code

25-100% increase in development speed

22 of 70

Componeeeeeents FTW!!!

23 of 70

Simple & reusable

Not only view

Services Router

Directives HTTP

Pipes Forms

Components Testing

24 of 70

github.com/dart-lang/angular_components

25 of 70

github.com/dart-lang/angular_components

...

26 of 70

Great apps

need a backend!

27 of 70

Needed

Lots of implementation

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

28 of 70

For a simple app...

29 of 70

Hello Firebase!

30 of 70

Realtime Database

Authentication

Cloud Storage

Messaging

Hosting

...

firebase.google.com

31 of 70

DEMO

TIME

@Janamou #DevFestCZ

32 of 70

Include Js SDK

package:firebase

package:angular

+

33 of 70

name: firebase_demo_ng

description: AngularDart and Firebase app

...

dependencies:

angular: ^4.0.0

angular_forms: ^1.0.0

firebase: ^4.0.0

...

pubspec.yaml

34 of 70

name: firebase_demo_ng

description: AngularDart and Firebase app

...

dependencies:

angular: ^4.0.0

angular_forms: ^1.0.0

firebase: ^4.0.0

...

->

->

pubspec.yaml

35 of 70

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

36 of 70

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

37 of 70

import 'package:angular/angular.dart';

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ]

)

class AppComponent {

// Here is the implementation

}

app_component.dart

38 of 70

import 'package:angular/angular.dart';

@Component(

selector: 'my-app',

templateUrl: 'app_component.html',

directives: const [ ... ]

)

class AppComponent {

// Here is the implementation

}

app_component.dart

->

39 of 70

<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

40 of 70

<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

->

41 of 70

@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

42 of 70

@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

->

43 of 70

<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

44 of 70

Sign in with Google

Read from realtime database

Save to realtime database

Upload to storage

45 of 70

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)

...

46 of 70

Structure the data

{

"notes" : {

"-KUsbAq6445-ynO4lg6Z" : {

"img_url" : "dart.png",

"text" : "Is awesome!",

"title" : "Dart"

},

...

}

}

47 of 70

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

48 of 70

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

try {

await dbRef

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

.future;

} catch (e) {

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

}

49 of 70

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");

}

50 of 70

Where should I put Firebase?

Component? Which?

Create a Service

51 of 70

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

52 of 70

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

53 of 70

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

54 of 70

@Component(...)

class NotesComponent implements OnInit {

FirebaseService service;

List<Note> notes = [];

NotesComponent(this.service);

@override

ngOnInit() {

notes = service.notes;

}

}

notes_component.dart

55 of 70

@Component(...)

class NotesComponent implements OnInit {

FirebaseService service;

List<Note> notes = [];

NotesComponent(this.service);

@override

ngOnInit() {

notes = service.notes;

}

}

->

->

notes_component.dart

56 of 70

<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

57 of 70

+

58 of 70

JavaScript

array

undefined

object

function

null

59 of 70

firebase.google.com/docs/reference

`

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

60 of 70

@JS('firebase.app')

library firebase.app_interop;

import 'package:js/js.dart';

// Other imports...

package:js

firebase-dart/.../app_interop.dart

61 of 70

@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

62 of 70

@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

63 of 70

@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

64 of 70

Do I need to write this

manually?!

TypeScript types definition file?

js_facade_gen library

65 of 70

+

=

66 of 70

Productivity, performance,

and stability

67 of 70

“Backend without

implementing backend”

68 of 70

You can port any JavaScript

library to Dart

69 of 70

Thank You!

Questions?

Jana Moudra @Janamou #DevFestCZ

70 of 70

Images