PRELUDE: This is the second article in a series of articles where my dear friend Siddharth(who’s a fellow GDE in Angular & Web Tech) and I create KittyGram: A super-minimal Instagram Clone that allows uploading only Cat 🐱 Photos.
Please find more information regarding the project overview and what we’ve implemented so far in our first article:
siddajmera image Implement Google Sign-In(OAuth) in your Angular App in under 15 minutes 🚀
Siddharth Ajmera 🇮🇳 ・ Apr 12 ・ 13 min read
#angular #typescript #javascript #webdev

In this article, we’ll cover the feature of uploading files to a Firebase Storage Bucket using Firebase Storage and Reactive Forms in Angular.
You’ll get the best learning experience out of this article, if you have a basic understanding of Angular, Angular Material and Firebase is relevant.
If you already took some steps inside Angular development together with Angular Material and like to know more about it, this article is absolutely perfect for you. 🙂

I’ve also added a Tl;DR; below if you would like to directly jump to a specific section of my article 🐾

Tl;DR:
Using the ReactiveFormsModule 😼
Adding needed AngularMaterialModules 💄
Using reactive Forms 🤓
Setting up Angularfire Storage 🅰️🔥
Enabling the Firebase Storage 🔥
Creating the StorageService inside our App 📚
To be continued 👣
Some final words 🧡
Perfect! Let’s go ahead and start implementing our feature to upload cute cat pictures.

Using the ReactiveFormsModule 😼
As we previously have set up our Angular Application, we also already created the CreateComponent and added the belonging /create route to enable navigation.

But how can we upload our cute cat image with a super cute description? We also might need a proper validation of the uploaded files to ensure the file format is indeed an image.

This sounds like a lot we need to consider, but let’s do it one step at a time.

Let’s first create the whole UI of our CreateComponent so it will look similiar to this:

Alt Text

Adding needed AngularMaterialModules to our AppMaterialModule 💄
Since we will use Input forms, a small progress bar and wrap it up all together inside a nice Display card we need to import the following AngularMaterialModules as well inside our AppMaterialModule:


import { MatCardModule } from ‘@angular/material/card’;
import { MaterialFileInputModule } from ‘ngx-material-file-input’;
import { MatFormFieldModule } from ‘@angular/material/form-field’;
import { MatInputModule } from ‘@angular/material/input’;
import { MatProgressBarModule } from ‘@angular/material/progress-bar’;

@NgModule({
exports: [

MatCardModule,
MaterialFileInputModule,
MatFormFieldModule,
MatInputModule,
MatProgressBarModule,

],
})
export class AppMaterialModule {}
IMPORTANT You might have recognized that we also imported another Module called MaterialFileInputModule from ngx-material-file-input

This was crucial for having an input with type=file being used inside the Angular Material mat-form-field.

Using reactive Forms 🤓
So far so good, the next necessary step we need to take is importing the ReactiveFormsModule inside our AppModule:


import { ReactiveFormsModule } from ‘@angular/forms’;

@NgModule({

imports: [

ReactiveFormsModule,
],

})
export class AppModule {}
Nice, this enables us to use reactive forms inside our components.

Let’s do it! 💪 Let’s implement our form to upload pictures:

create.component.ts

import { Component, OnDestroy, OnInit } from ‘@angular/core’;
import {
AbstractControl,
FormBuilder,
FormGroup,
Validators,
} from ‘@angular/forms’;
import { Observable, Subject } from ‘rxjs’;
import { takeUntil } from ‘rxjs/operators’;

import { AuthService } from ‘…/…/services/auth/auth.service’;
import { UtilService } from ‘…/…/services/util/util.service’;

@Component({
selector: ‘app-create’,
templateUrl: ‘./create.component.html’,
styleUrls: [‘./create.component.scss’],
})
export class CreateComponent implements OnInit, OnDestroy {
destroy$: Subject = new Subject();
fileToUpload: File;
kittyImagePreview: string | ArrayBuffer;
pictureForm: FormGroup;
user: firebase.User;

constructor(
private readonly authService: AuthService,
private readonly formBuilder: FormBuilder,
private readonly utilService: UtilService,

) {}

ngOnInit() {
this.pictureForm = this.formBuilder.group({
photo: [null, Validators.required],
description: [null, Validators.required],
});

this.authService.user$
  .pipe(takeUntil(this.destroy$))
  .subscribe((user: firebase.User) => (this.user = user));

}

ngOnDestroy() {
this.destroy$.next(null);
}
}
First, let’s inject the FormBuilder. It helps us to create a FormGroup that structures our whole form. Since we just need the photo and a small description we’ll just add two FromControls to our .group({[…],[…]})function.

That said, we also pass a default Value inside the FormControls (which is nullin our case) and one or many Form Validator/s, which are helping us, to validate the user input.

By doing so, we can either pass a Built-in Validator shipped by the @angular/forms module (Like the Required one we are using here) or implementing a custom Validator.

Since we want to be sure that the uploaded file is actually an image type we do need to implement this as a custom Validator.

Let’s call this validator image:

private image(
photoControl: AbstractControl,
): { [key: string]: boolean } | null {
if (photoControl.value) {
const [kittyImage] = photoControl.value.files;
return this.utilService.validateFile(kittyImage)
? null
: {
image: true,
};
}
return;
}
And add it to the FormControl named photo:

this.pictureForm = this.formBuilder.group({
photo: [
null,
[Validators.required, this.image.bind(this)],
],

});
The Validator calls a UtilService and checks, if the uploaded file type is an image:

util.service.ts

import { Injectable } from ‘@angular/core’;

@Injectable({
providedIn: ‘root’,
})
export class UtilService {
private imageFileTypes = [

‘image/apng’,
‘image/bmp’,
‘image/gif’,
‘image/jpeg’,
‘image/png’,
‘image/svg+xml’,

];

validateFile(file: File): boolean {
return this.imageOrVideoFileTypes.includes(file.type);
}
}
If the evaluation of the user input fails by one of our Validators, the whole form - and of course the assigned FormControl itself - will turn immediately into an invalid state, hence we can react according to the thrown error. We’ll come back to this point later inside our template code.

#angular #angular9 #firebase #angular-material #firebase-storage

Implement file upload with Firebase Storage 🔥 in our Angular App: The simple way
9.30 GEEK