In this tutorial, I'm going to show you how to create a simple PWA that you can install on your phone. This PWA will be able to create and read QR codes. With this app, you will have more control of your guests for your next event!
In this app, we are going to pretend this is a registration app for your event.
The final code:
https://github.com/devpato/angular-pwa-qrcode
Live App:
https://qr-app-79289.firebaseapp.com/
Let's create an angular app!
1) Run, then when asked to create routing, click yes. Then, when asked to select a CSS processor, select SCSS.
ng new qr-app
2) Let's create our app into a PWA (Progressive Web App) so we can install the app on our phone. Inside of your project, in your command line run:
ng add @angular/pwa
3) Create a registration component.
ng g c registration
4) Create a scanner component.
ng g c scanner
5) Create a guest-list component.
ng g c guest-list
6) Create a guest service.
ng g s guest
7) Create the navbar component.
ng g c navbar
8) Install the following packages inside of your project:
//This is the package that scans QR codes
npm i @zxing/ngx-scanner
//This is the packages that generates QR codes
npm i ngx-qrcode2
//This is the package used to generate a random id for your users
npm i uuid
9) Go to your index.html and add the Semantic UI CDN to give some styling to our app.
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css"
integrity="sha256-9mbkOfVho3ZPXfM7W8sV2SndrGDuh7wuyLjtsWeTI1Q="
crossorigin="anonymous"
/>
10) Navigate to your registration.component.ts file then copy/paste the following code:
import { FormBuilder } from "@angular/forms";
import { Validators } from "@angular/forms";
import { v4 as uuid } from "uuid";
import { GuestService } from "../guest.service";
import { Router } from "@angular/router";
.
.
.
export class RegistrationComponent implements OnInit {
registrationForm = this.fb.group({
firstName: ["", Validators.required],
lastName: ["", Validators.required]
});
constructor(
private fb: FormBuilder,
private guestService: GuestService,
private router: Router
) {}
ngOnInit() {}
onSubmit(): void {
const guest = { ...this.registrationForm.value, id: uuid() };
guest.qr = JSON.stringify(guest);
this.guestService.addGuest(guest);
this.registrationForm.reset();
this.router.navigate(["/guests"]);
}
}
11) Navigate to your registration.component.scss file then copy/paste the following code:
.registration {
text-align: center;
margin: 8px;
&-form {
form {
display: flex;
flex-direction: column;
.field {
margin: 8px;
}
}
}
}
12) Navigate to your registration.component.html file then copy/paste the following code. The following code will generate a new guest which will be the info inside of our QR code.
<div class="registration">
<h2>QR Code Registration App!</h2>
<span>Please enter your information to register for the event.</span>
<div class="registration-form">
<form [formGroup]="registrationForm" (ngSubmit)="onSubmit()">
<div class="ui left corner labeled input field">
<input
type="text"
placeholder="Fist Name"
formControlName="firstName"
/>
<div class="ui left corner label">
<i class="asterisk icon"></i>
</div>
</div>
<div class="ui left corner labeled input field">
<input type="text" placeholder="Last Name" formControlName="lastName" />
<div class="ui left corner label">
<i class="asterisk icon"></i>
</div>
</div>
<button
class="ui inverted orange button"
type="submit"
[disabled]="!registrationForm.valid"
>
Registration
</button>
</form>
</div>
</div>
13) Navigate to your navbar.component.html file then copy/paste the following code:
<div class="ui three item menu">
<a class="item" [routerLink]="['']">Registration</a>
<a class="item" [routerLink]="['/scanner']">QR Scanner</a>
<a class="item" [routerLink]="['/guests']">Guest</a>
</div>
14) Navigate to your guest-list.component.ts file then copy/paste the following code:
import { GuestService } from "../guest.service";
.
.
.
guestList$ = this.guestService.guests$;
elementType: "url" | "canvas" | "img" = "url";
constructor(private guestService: GuestService) {}
ngOnInit() {}
15) Navigate to your guest-list.component.html file then copy/paste the following code:
<div class="guest-list">
<table class="ui celled table" *ngIf="guestList$ | async as guestList">
<tbody>
<tr *ngFor="let g of guestList">
<td data-label="firstName">{{ g.firstName }}</td>
<td data-label="lastName">{{ g.lastName }}</td>
<td data-label="qr">
<ngx-qrcode
[qrc-element-type]="elementType"
[qrc-value]="g.qr"
class="qrcode"
></ngx-qrcode>
</td>
</tr>
</tbody>
</table>
</div>
16) Navigate to your guest-list.component.scss file then copy/paste the following code:
.qrcode {
display: flex;
justify-content: center;
}
17) Navigate to your scanner.component.ts file then copy/paste the following code:
import { Guest } from "../guest.model";
import { GuestService } from "../guest.service";
import { map } from "rxjs/operators";
.
.
.
availableDevices: MediaDeviceInfo[];
currentDevice: MediaDeviceInfo = null;
hasDevices: boolean;
hasPermission: boolean;
qrResult: Guest;
guestExist: boolean;
constructor(private guestService: GuestService) {}
ngOnInit(): void {}
//Clears the QR code scanned
clearResult(): void {
this.qrResult = null;
}
//Scans the QR code
onCodeResult(resultString: string): void {
this.guestExist = null;
if (this.checkQRJSON(resultString)) {
this.qrResult = JSON.parse(resultString);
this.checkInGuest(this.qrResult);
this.clearMessage();
} else {
this.guestExist = false;
this.clearMessage();
}
}
//Permission for the app to use the device camera
onHasPermission(has: boolean): void {
this.hasPermission = has;
}
//Checks if the QR code belongs to a valid guest
checkInGuest(guestQR: Guest): void {
this.guestService.guests$
.pipe(
map(guests =>
guests.find((guest: Guest) => guest.id === guestQR.id)
)
)
.subscribe(guest => {
if (guest !== null && guest !== undefined) {
this.guestExist = true;
} else {
this.guestExist = false;
}
this.clearResult();
this.clearMessage();
});
}
clearMessage() {
setTimeout(() => {
this.guestExist = null;
}, 3000);
}
//This function check if the QR code has a valid JSON as data
checkQRJSON(qrString: string): boolean {
if (
/^[\],:{}\s]*$/.test(
qrString
.replace(/\\["\\\/bfnrtu]/g, "@")
.replace(
/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
"]"
)
.replace(/(?:^|:|,)(?:\s*\[)+/g, "")
)
) {
return true;
} else {
return false;
}
}
18) Navigate to your scanner.component.html file then copy/paste the following code:
<div class="qr-scan-area">
<!-- This is the NPM package in-charge of scanning the QR -->
<zxing-scanner
#scanner
[(device)]="currentDevice"
(scanSuccess)="onCodeResult($event)"
(permissionResponse)="onHasPermission($event)"
></zxing-scanner>
<div class="qr-area">
<div class="area"></div>
</div>
</div>
<!-- Displays message on the screen if guest is valid or not -->
<div class="guest">
<ng-container *ngIf="guestExist">
<div class="ui success message">
<i class="close icon"></i>
<div class="header">
Welcome!!
</div>
<p>Guest has been found on the guest lists</p>
</div>
</ng-container>
<ng-container #notFound *ngIf="guestExist === false">
<div class="ui negative message">
<i class="close icon"></i>
<div class="header">
Warning!
</div>
<p>This person is not a guest!</p>
</div>
</ng-container>
</div>
19) Navigate to your scanner.component.scss file then copy/paste the following code. In this CSS, we are drawing a red square to make the scanner look cooler but it is not needed for the scanner to work.
::ng-deep {
.qr-scan-area {
position: relative;
zxing-scanner {
max-width: 100%;
}
.qr-area {
position: absolute;
display: flex;
justify-content: center;
align-items: center;
height: calc(100% - 50px);
top: 0;
width: 100%;
.area {
height: 200px;
width: 200px;
border: 2px solid red;
}
}
}
}
20) Inside of the app folder, create a new interface with the following name: guest.model.ts
21) Inside of your guest.model.ts copy/paste the following:
export interface Guest {
id: string;
firstName: string;
lastName: string;
qr?: string;
}
22) Now, navigate to the guest service you previously created. guest.service.ts. The following code is the code that will handle populated dummy data to start with as well as adding every new guest created to the array of guest.
import { Guest } from "./guest.model";
import { BehaviorSubject } from 'rxjs';
.
.
.
private guestSource = new BehaviorSubject<Guest[]>(null);
guests$ = this.guestSource.asObservable();
private guests = [
{
id: "7558e6e5-3cfa-4c24-b5b7-653ecbd49925",
firstName: "Pato",
lastName: "Vargas"
},
{
id: "4847498c-b57f-4ceb-8c0c-8831b9972158",
firstName: "Diego",
lastName: "Maradona"
}
];
constructor() {
this.populateQR();
this.guestSource.next(this.guests);
}
populateQR(): void {
this.guests.forEach((g: Guest) => (g.qr = JSON.stringify({ ...g })));
}
addGuest(newGuest: Guest): void {
this.guests.push(newGuest);
this.guestSource.next(this.guests);
}
23) Go to your app.module.ts and add the following modules to your code:
import { NgxQRCodeModule } from "ngx-qrcode2";
import { ZXingScannerModule } from "@zxing/ngx-scanner";
import { ReactiveFormsModule } from "@angular/forms";
.
.
.
imports: [
BrowserModule,,
AppRoutingModule,
ServiceWorkerModule.register("ngsw-worker.js", {
enabled: environment.production
}),
ReactiveFormsModule,
ZXingScannerModule,
NgxQRCodeModule
]
24) Finally, we need to create the routes for our app. Copy and paste the following code:
import { RegistrationComponent } from "./registration/registration.component";
import { GuestListComponent } from "./guest-list/guest-list.component";
import { ScannerComponent } from "./scanner/scanner.component";
const routes: Routes = [
{
path: "",
component: RegistrationComponent
},
{
path: "guests",
component: GuestListComponent
},
{
path: "scanner",
component: ScannerComponent
}
];
25) Go to your app.component.html and erase everything that is in there and copy/paste the following:
<app-navbar></app-navbar>
<router-outlet></router-outlet>
26) Time to test our app. Run the app with ng serve --o. You should see the following:
Time to use our PWA in our phone.
1) First run:
ng build --prod
2) Deploy your app to your favorite hosting provider. I like Firebase. It's very easy to deploy. (I'm not going to show you how to do so, so please google it).
3) Once your app has been deployed, go to your phone and navigate to the URL where your app is living.
4) Once the app opens, it will ask you if you want to add your app to your home screen because it is a PWA; like the picture below shows.
Top comments (0)