From this article, you will get Angularfire2 = Awesome SPA (single page application) at your fingertips using Angular and Firebase.
Angularfire2 is really a great library to work with Angular and Firebase. In this tutorial, I am going to show you how you can build the application using Firebase and Angular. And in the end, I will show you how you can host your application to Firebase. In short, I am going to show how you can create the application from scratch to deployment. Are you guys ready to dive in with me?? Yeah! so let’s get started...
Objective
We are going to build a simple application in which I will cover the following operations.
- Display all products
- Add product
- Delete product
- Update product
- Upload files to Firebase storage
- Deploy Angular application on Firebase hosting
Prerequisites
Setting up Firebase
- First, visit the https://www.firebase.com/
- Then, click on "See our new Website" and at the top-right corner, you will find "Go to Console". Just click on that and login to your account; else visit https://console.firebase.google.com/ and login.
- From console, click on "Create new project".
Go to Authentication tab and click on Web Setup at the top-right corner to get the configuration.
Then, click on Database button to set rules for database and navigate to Rules tab and write as shown below.
Now, navigate back to Data tab and create a child under the root node which is the name of your project.
Now, click on Storage tab to enable storage of images, and create one folder, as shown below.
After creating directory inside storage, don’t forget to set its rules, by navigating to Rules tab.
So far, we have created a Firebase project which enables the authentication using email and password, and created a database which is given both, read and write permissions, and also enabled the storage to store the photos of uploaded products. So now, we are ready to dive in.
Angular side:
- Angular CLI should be > 1.0.6 (latest is most preferable)
- If you don’t know how to upgrade your current cli, just follow the following steps -
- npm uninstall –g @angular/cli (it will remove current Angular Cli)
- npm cache clean ( It will clean the cache)
- npm install –g @angular/cli@latest (it will install the latest cli)
- If you don’t know how to install Angular Cli or you are new to Angular Cli, Please Follow my blog here for stp by step guide on how to install Angular Cli.
- Now, if you are done with Angular Cli, we will create the new application.
- ng new firebasecrudDemo (it will create new Angular application)
- Then, navigate to the directory in which we had created the firebasecrudDemo project. Inside the firebasecrudDemo directory write the following command in your command prompt or power shell,
- npm install firebase angularfire2 - -save (it will install angularfire2 library )
Setting app.modult.ts
Now, first of all, we need to set the web configuration (remember which I had copied from Firebase!) as shown below.
- export const firebaseconfig=
- {
- apiKey: "",
- authDomain: "",
- databaseURL: "",
- projectId: "",
- storageBucket: "",
- messagingSenderId: ""
- }
And import it in Imports array of app.module.ts file.
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule, AngularFireModule.initializeApp(firebaseconfig)
- ]
Also import the following packages to provide two services
- angularfireauth (which is required for user authentication and creation)
- angularfiredatabase (which is required for connecting with database)
- import { AngularFireModule } from "angularfire2";
- import { AngularFireDatabase } from "angularfire2/database";
-
- providers: [AngularFireDatabase]
So, our final app.module.ts will look like following.
- import { BrowserModule } from '@angular/platform-browser';
- import { NgModule } from '@angular/core';
- import { FormsModule } from '@angular/forms';
- import { HttpModule } from '@angular/http';
-
- import { AppComponent } from './app.component';
- import { AngularFireModule } from "angularfire2";
- import { AngularFireDatabase } from "angularfire2/database";
-
-
- export const firebaseconfig=
- {
-
- apiKey: "",
- authDomain: "",
- databaseURL: "",
- projectId: "",
- storageBucket: "",
- messagingSenderId: ""
- }
- @NgModule({
- declarations: [
- AppComponent
- ],
- imports: [
- BrowserModule,
- FormsModule,
- HttpModule,
- AngularFireModule.initializeApp(firebaseconfig)
- ],
- providers: [AngularFireDatabase],
- bootstrap: [AppComponent]
- })
- export class AppModule { }
Add new Products to Database
As we had created an empty database first, we need to insert a record in the database. We are using Firebase database which is NoSQL database, so we don’t need to create table and columns and everything. We just need to create a root which we have created in previous steps and named that root to products.
Will divide this process in the following steps.
Design for add new product
- <div class="row">
- <div class="container">
- <h2>Add Product</h2>
- <div class="form-group">
- <input type="text" placeholder="Enter name of the Product" class="form-control" #field >
- </div>
- <div class="form-group">
- <input type="number" placeholder="Enter price" class="form-control" #price >
- </div>
- <div class="form-group">
- <input class="form-control" (change)="upload(f,img)" type="file" #f/>
- </div>
- <div class="form-group">
- <img height="100" width="100" alt="Preview Will be displayed here" src="" #img>
- </div>
- <button (click)="add(field,img,price)" class="btn btn-primary">Add Product</button>
- </div>
- </div>
Imports
- import { AngularFireDatabase, FirebaseListObservable } from "angularfire2/database";
- import 'firebase/storage'
- import * as firebase from 'firebase';
-
- constructor(public _database: AngularFireDatabase) {}
AngularFireDatabase is required for making connection with database and it will also provide us various methods for add, update, delete, and display products.
FirebaseListObservable is used to store data which is retrieved from database.
Firebase/Storage is used to upload the images or files to Firebase storage.
Create an array of type FirebaseListObservable and upload task
- arr: FirebaseListObservable<any[]>;
- public uploadTask: firebase.storage.UploadTask;
Upload method (for uploading file to firebase storage)
- upload(f, img) {
- let storageReference = firebase.storage().ref('/images/' + f.files[0].name);
- this.uploadTask = storageReference.put(f.files[0]);
- this.uploadTask.on('state_changed', function (snapshot) {
-
- }, function (error) {
-
- }, function () {
-
-
- storageReference.getDownloadURL().then(function (url) {
-
- img.src = url;
-
- });
-
- });
- }
Here upload method has two arguments, f is a reference of input control which we had put on our html page and same img is reference of our img control.
Add method
- add(field,img,price) {
- this.arr.push({ pname: field.value, createdAt: new Date().toString(),price:price.value, likes: 0,image:img.src});
-
- }
So here in Add method I am using push method of array , inside the push method I am creating the object which I need to store to database. So now our root products have the following nodes
pname, createdAt, price, likes, and image. Remember, Firebase is NoSQL database, so it will store the data as tree structure. The parameter fields, img and price are the references of their corresponding html elements.
Display Products
Now, as we are done with adding a new product, it’s time to fetch the records from the database.
Html for products display
- <div class="row">
- <hr>
- <div class="container">
- <h2>Products</h2>
- <div class="row">
- <div class="col-md-4 zweet-card" *ngFor="let item of arr | async">
- <div class="panel panel-default">
- <div class="panel-body">
- <strong>{{item.pname}}</strong> <br /> {{item.price | currency:'INR':true }}<br />
- <small>{{item.createdAt| date: 'd/M/y H.m a'}}</small>
- <img height="100" width="100" src="{{item.image}}">
- <div class="btn btn-danger btn-sm btn-remove" (click)="remove(item.$key)">
- <i class="glyphicon glyphicon-remove"></i>
- </div>
- <div class="btn btn-info btn-sm pull-right btn-like" (click)="like(item.$key,item.likes)">
- <div class="badge badge-like-count">{{item.likes}}</div>
- <i class="glyphicon glyphicon-thumbs-up"></i>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
Code for products display
- arr: FirebaseListObservable<any[]>;
- ngOnInit() {
- this.arr = this._database.list('/products');
- }
Which will fetch all the records from the database with root named as products and bind all the records to html asynchronously using that async pipe.
Delete Product
- remove($key) {
- this.arr.remove($key);
- }
In Firebase when we add new record to database it will automatically generate the unique key or token which will be used to fetch the particular record uniquely . So I am using that key value to remove the particular record from database.
Update Likes for Products
- like($key, like) {
- this.arr.update($key, { likes: like + 1 });
- }
This will update total like count on particular product. So here I am passing two arguments, first is that unique key and the second is to update.
Final Source Code
App.component.html
- <div class="row">
- <div class="container">
- <h2>Add Product</h2>
- <div class="form-group">
- <input type="text" placeholder="Enter name of the Product" class="form-control" #field >
- </div>
- <div class="form-group">
- <input type="number" placeholder="Enter price" class="form-control" #price >
- </div>
- <div class="form-group">
- <input class="form-control" (change)="upload(f,img)" type="file" #f/>
- </div>
- <div class="form-group">
- <img height="100" width="100" alt="Preview Will be displayed here" src="" #img>
- </div>
- <button (click)="add(field,img,price)" class="btn btn-primary">Add Product</button>
- </div>
- </div>
- <div class="row">
- <hr>
- <div class="container">
- <h2>Products</h2>
- <div class="row">
- <div class="col-md-4 zweet-card" *ngFor="let item of arr | async">
- <div class="panel panel-default">
- <div class="panel-body">
- <strong>{{item.pname}}</strong> <br /> {{item.price | currency:'INR':true }}<br />
- <small>{{item.createdAt| date: 'd/M/y H.m a'}}</small>
- <img height="100" width="100" src="{{item.image}}">
- <div class="btn btn-danger btn-sm btn-remove" (click)="remove(item.$key)">
- <i class="glyphicon glyphicon-remove"></i>
- </div>
- <div class="btn btn-info btn-sm pull-right btn-like" (click)="like(item.$key,item.likes)">
- <div class="badge badge-like-count">{{item.likes}}</div>
- <i class="glyphicon glyphicon-thumbs-up"></i>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
- </div>
App.component.ts
- import { Component,OnInit } from '@angular/core';
- import { AngularFireDatabase, FirebaseListObservable } from "angularfire2/database";
- import 'firebase/storage'
- import * as firebase from 'firebase';
- @Component({
- selector: 'app-root',
- templateUrl: './app.component.html',
- styleUrls: ['./app.component.css']
- })
- export class AppComponent implements OnInit {
- arr: FirebaseListObservable<any[]>;
- public uploadTask: firebase.storage.UploadTask;
- constructor(public _database: AngularFireDatabase) {}
- ngOnInit() {
- this.arr = this._database.list('/products');
- }
- add(field,img,price) {
- this.arr.push({ pname: field.value, createdAt: new Date().toString(),price:price.value, likes: 0,image:img.src});
-
- }
- remove($key) {
- this.arr.remove($key);
- }
- like($key, like) {
- this.arr.update($key, { likes: like + 1 });
- }
- upload(f, img) {
-
- let storageReference = firebase.storage().ref('/images/' + f.files[0].name);
- this.uploadTask = storageReference.put(f.files[0]);
- this.uploadTask.on('state_changed', function (snapshot) {
-
-
-
- var progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
- console.log('Upload is ' + progress + '% done');
-
- switch (snapshot.state) {
- case firebase.storage.TaskState.PAUSED:
- console.log('Upload is paused');
- break;
- case firebase.storage.TaskState.RUNNING:
- console.log('Upload is running');
- break;
- }
- }, function (error) {
-
- }, function () {
-
-
-
- storageReference.getDownloadURL().then(function (url) {
-
- img.src = url;
-
- });
-
- });
- }
- }
Isn’t it easy guys? Now we will see how to host angular application on firebase hosting. Excited? Let’s dive in to it.
Deploy Angular Application on Firebase Hosting
We had already created project on firebase using console, so now we are only required to install firebase cli. To do so navigate to your project directory in command prompt and write the following code.
npm install –g firebase-tools
firebase login
firebase init
It will ask you few questions like what features of firebase cli you want to use? In our case select hosting only using space.
Second question it will ask for project directory -- > then select the directory of your project which you have created using firebase console.
What do you want to use as your public directory? In our case the name of the public directory should be dist (which we are going to create shortly).
Configure as a single page application? Yes
Initiation is completed.
Now it is time to create build of your project which was just created.
To generate build using angular cli navigate to your project directory in command prompt and write the following code.
ng build - -prod - - aot
it will generate a build using ahead of time compilation.
Now the final step is,
firebase deploy
Conclusion
We covered a lot in this tutorial - Setting up the Firebase project, Creating Angular project, Add new product, Display product, Delete product, Deploy Angular application on Firebase Hosting and many more. I hope it will be helpful to you.
You can download the source code from here.